ファイルの作成時間を見つけるにはどうすればよいですか?


64

この問題に関するいくつかの記事を読んだときに、ファイルの作成時間を見つける必要がありますが、すべて解決策はありません(Site1Site2など)。

statコマンドを実行しようとすると、が表示されます Birth: -

それでは、どのようにしてファイルの作成時間を見つけることができますか?


2
ファイルの「作成時間」が正確であるとは限らないことに注意してください。ファイルの作成日を「ごまかす」方法はたくさんあります。
トーマス・ウォード

1
@ThomasWard他のファイルデータを偽造する方法よりも多くのことがありますか
シーズティマーマン

回答:


67

ディレクトリの作成日を知る方法があります。次の手順に従ってください。

  1. コマンドでディレクトリのiノードを知るls -i(たとえば、そのXを言う)

  2. df -T /pathコマンドでディレクトリが保存されているパーティションを確認します(オンと言います /dev/sda1

  3. 次のコマンドを使用します。 sudo debugfs -R 'stat <X>' /dev/sda1

出力に表示されます:

crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013

crtime はファイルの作成日です。

私がテストしたもの

  1. 特定の時間にディレクトリを作成しました。
  2. それにアクセスしました。
  3. ファイルを作成して変更しました。

  4. 私はコマンドを試しましたが、それは正確な時間を与えました。

  5. それから私はそれを修正し、再度テストします、crtimeは同じままでしたが、修正しアクセス時間は変わりました。

私はので、私はよりよく理解することができますについて議論したいので、私は、私は人々がLinuxは、この機能をサポートしていないと言う理由を不思議に思うよ、このポスト
NUX

13
Linux自体はそうではないからです。ext4ファイルシステムにはこの情報がありますが、カーネルはそれにアクセスするためのAPIを提供しません。どうやら、debugfsファイルシステムから直接抽出するので、カーネルのAPIを使用する必要はありません。こちらをご覧ください
テルドン

私はそれをテストしました。ext4ファイルシステムで完全に動作しました
Fahim Babar Patel

1
これはext4固有のようです?私にとってはXFSではうまくいきませんでした。
Quantum7

カーネル、glibc、およびcoreutilsはすべて、statx()2019
。– hippietrail

54

@Nuxはこれに対するすばらしい解決策を見つけまし。すべてを直接実行するために使用できる小さな関数を作成することにしました。これをに追加するだけ ~/.bashrcです。

get_crtime() {

    for target in "${@}"; do
        inode=$(stat -c '%i' "${target}")
        fs=$(df  --output=source "${target}"  | tail -1)
        crtime=$(sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null | 
        grep -oP 'crtime.*--\s*\K.*')
        printf "%s\t%s\n" "${target}" "${crtime}"
    done
}

これで、get_crtime好きなだけファイルまたはディレクトリの作成日を印刷することができます:

$ get_crtime foo foo/file 
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014

(それはのようにファイルがコピーである場合は、作成日は、元のファイルの作成日ではないことに注意され変更日で)。ファイルがコピーされると、変更日は元の日付になりますが、作成日はコピーの日付になります。(この質問には誤解があります:askubuntu.com/questions/529885/…
ジェイコブVlijm 14

1
@JacobVlijmええ、もちろんです。それは明らかではないですか?それ以外の場合はどうでしょうか?コピーとは、たまたま同じ内容を持つ新しいファイルです。ちなみにコピーの変更時間も変わります。使用cp -pまたは同様のことを行わないように明示的に選択しない限り、コピーが作成された瞬間に設定されます。
テルドン

絶対に、しかし同時に、modのように、それはそれほど非論理的ではないでしょう。日付、ファイル内のどこかに、日付が作成されたときに保存されます。リンクされた質問に答えるまで、そうではなかったことを知らなかったことを認めなければなりません。
ジェイコブVlijm 14

ちなみに、私はnautilusでファイルをコピーしましたが、変更日はそのまま(以前)のままですm 日付は作成日より前です。
ジェイコブVlijm 14

1
@demongolemはい、CentOSバージョンはdfこの--outputオプションをサポートしていないようです。その場合、その行を置き換えることができfs=$(df foo | awk '{a=$1}END{print a}'、関数も機能します。この回答で示しているのは、ファイル/ディレクトリターゲットに対して直接実行できる方法で、受け入れられた回答からコマンドをラップする方法です。
テルドン

11

stat作成時間を表示できないのは、stat(2)システムコールの制限によるものです。システムコールの戻り構造体には、作成時間のフィールドが含まれていません。ただし、Linux 4.11(17.10以降)以降では、新しいstatx(2)システムコールを使用できます。これには、戻り構造体に作成時間が含まれています。

*おそらく、ハードウェアイネーブルメントスタック(HWE)カーネルを使用する古いLTSリリースで。確認のuname -rために、少なくとも4.11でカーネルを使用しているかどうかを確認します。

残念ながら、Cプログラムでシステムコールを直接呼び出すのは簡単ではありません。通常、glibcは作業を簡単にするラッパーを提供しますが、glibcはstatx(2)2018年8月(バージョン2.28、18.10で利用可能)にのみラッパーを追加しました。幸いなことに、@ whotwagnerはstatx(2) x86およびx86-64システムでシステムコールを使用する方法を示すサンプルCプログラムを作成しました。出力は、stat書式設定オプションのないデフォルトと同じ形式ですが、出生時のみを印刷するように変更するのは簡単です。

まず、クローンを作成します。

git clone https://github.com/whotwagner/statx-fun

statx.cコードをコンパイルできます。または、誕生時間だけが必要な場合birth.cは、次のコードを使用してクローンディレクトリにを作成します(statx.cナノ秒精度を含む作成タイムスタンプのみを印刷する最小バージョンです)。

#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>

// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>

/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif

#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))

int main(int argc, char *argv[])
{
    int dirfd = AT_FDCWD;
    int flags = AT_SYMLINK_NOFOLLOW;
    unsigned int mask = STATX_ALL;
    struct statx stxbuf;
    long ret = 0;

    int opt = 0;

    while(( opt = getopt(argc, argv, "alfd")) != -1)
    {
        switch(opt) {
            case 'a':
                flags |= AT_NO_AUTOMOUNT;
                break;
            case 'l':
                flags &= ~AT_SYMLINK_NOFOLLOW;
                break;
            case 'f':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_FORCE_SYNC;
                break;
            case 'd':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_DONT_SYNC;
                break;
            default:
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (optind >= argc) {
        exit(EXIT_FAILURE);
    }

    for (; optind < argc; optind++) {
        memset(&stxbuf, 0xbf, sizeof(stxbuf));
        ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
        if( ret < 0)
        {
            perror("statx");
            return EXIT_FAILURE;
        }
        printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
    }
    return EXIT_SUCCESS;
}

次に:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

理論的には、これにより作成時間がよりアクセスしやすくなります。

  • ext *ファイルシステムよりも多くのファイルシステムをサポートする必要があります(debugfsext2 / 3/4ファイルシステム用のツールであり、他では使用できません)
  • これを使用するのにrootは必要ありません(makeやなどの必要なパッケージをインストールする場合を除くlinux-libc-dev)。

たとえば、xfsシステムをテストします。

$ truncate -s 1G temp; mkfs -t xfs temp; mkdir foo; sudo mount temp foo; sudo chown $USER foo
$ touch foo/bar
$ # some time later
$ echo > foo/bar
$ chmod og-w foo/bar
$ ./birth foo/bar | xargs -I {} date -d @{}
Mon Nov 27 14:43:21 UTC 2017
$ stat foo/bar                             
  File: foo/bar
  Size: 1           Blocks: 8          IO Block: 4096   regular file
Device: 700h/1792d  Inode: 99          Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/ muru)      Gid: ( 1000/ muru)
Access: 2017-11-27 14:43:32.845579010 +0000
Modify: 2017-11-27 14:44:38.809696644 +0000
Change: 2017-11-27 14:44:45.536112317 +0000
 Birth: -

ただし、これはNTFSおよびexfatでは機能しませんでした。それらのFUSEファイルシステムには作成時間は含まれていなかったと思います。


glibcがstatx(2)システムコールのサポートを追加した場合、またはそうなるとstatすぐに続きstat、このために単純な古いコマンドを使用できるようになります。しかし、新しいカーネルを入手したとしても、これがLTSリリースにバックポートされるとは思いません。だから、私は期待しないstat任意の現在のLTSリリース、これまで手動での介入なしに作成時刻を印刷する(14.04、16.04、または18.04)。

ただし、18.10では、statx説明されているように関数を直接使用できますman 2 statx(glibcがまだラッパーを追加していないことを示す18.18のマンページは間違っています)。


githubにリンクしていただきありがとうございます。数か月前に4.11がリリースされたときに検索しましたが、何も見つかりませんでしたが、それを忘れてしまいました。
WinEunuuchs2Unix

@ WinEunuuchs2unixはpingで許しますが、なぜmuruのアカウントにrepがあるのか​​をメタサイトで尋ねるのは賢明でしょう1か?
ジョージウドセン

@GeorgeUdosenそれは衝撃的です!私はなぜかの予感を持っている...
WinEunuuchs2Unix

@GeorgeUdosen一時停止についての最近のメタの質問があり、特定のユーザーには対応しません:meta.askubuntu.com/questions/18341 / ...チャットルームに今行くので、そこで会話を続けることができます願います。
WinEunuuchs2Unix

機能が利用可能になったので、そのフィールドを変更する方法を知っていますか?Pythonでctypesラッパーを作成しようとする場合があります。ありがとう。
グリンゴサーブ

3

TL; DR: 実行するだけですsudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

(fsを計算するには、実行しますdf -T /path/to/your/file。ほとんどの場合、実行されます/dev/sda1)。

ロングバージョン:

次の2つのコマンドを実行します。

  1. ファイルのパーティション名の名前を見つけます。

    df -T /path/to/your/file

    出力は次のようになります(パーティション名が最初です)。

    Filesystem     Type 1K-blocks    Used Available Use% Mounted on
    /dev/<your fs> ext4   7251432 3481272   3509836  50% /
    
  2. そのファイルの作成時間を調べます。

    sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
    

    出力で、を探しますctime

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.