如何找到文件的创建时间?

nux*_*nux 82 filesystem metadata stat

我需要找到一个文件的创建时间,当我阅读一些关于这个问题的文章时,都提到没有解决方案(如Site1Site2)。

当我尝试该stat命令时,它指出 Birth: -.

那么如何找到文件的创建时间呢?

nux*_*nux 72

有一种方法可以知道目录的创建日期,只需按照以下步骤操作:

  1. 通过命令知道目录的inodels -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
Run Code Online (Sandbox Code Playgroud)

crtime 是文件的创建日期。

我测试了什么

  1. 在特定时间创建了一个目录。
  2. 访问了它。
  3. 通过创建文件修改它。

  4. 我试过这个命令,它给出了一个确切的时间。

  5. 然后我修改它,再次测试,crtime保持不变,但修改访问时间改变了。

  • 因为 Linux 本身没有。ext4 文件系统确实有这些信息,但内核没有提供 API 来访问它。显然,`debugfs` 直接从文件系统中提取它,所以它不需要使用内核的 API。请参阅[此处](http://unix.stackexchange.com/a/50184/22222)。 (14认同)
  • 看起来这是 ext4 特有的?它对我来说不适用于 XFS。 (2认同)

ter*_*don 62

@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
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以运行get_crtime以打印任意数量的文件或目录的创建日期:

$ get_crtime foo foo/file 
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014
Run Code Online (Sandbox Code Playgroud)

  • @JacobVlijm 好吧,是的,当然。这不是很明显吗?不然怎么可能?副本是一个刚好与另一个文件具有相同内容的新文件。顺便说一下,副本的修改时间也会改变。它设置为创建副本的时刻,除非您明确选择使用 `cp -p` 或类似方法不发生这种情况。 (2认同)

mur*_*uru 17

无法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 中可用)。该stat命令本身statx(2)仅在 GNU coreutils 8.31(2019 年 3 月发布)中获得支持,但是,即使Ubuntu 20.04 也只有 coreutils 8.30

但我不认为这会被反向移植到 LTS 版本,即使它们确实获得或已经使用更新的内核或 glibcs​​。所以,我不希望stat任何当前的LTS版本(16.04,18.04和20.04)有史以来打印创建时间,无需人工干预。

在 18.10 和更新版本上,您可以直接使用中所述的statx函数man 2 statx(请注意,18.10 联机帮助页在说明 glibc 尚未添加包装器方面是不正确的)。

而在 Ubuntu 20.10 中,您将能够stat直接使用:

# stat --version
stat (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
# stat /
  File: /
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 88h/136d    Inode: 57279593    Links: 1
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-08-18 06:57:46.912243164 +0000
Modify: 2020-08-18 06:57:06.768492334 +0000
Change: 2020-08-18 06:57:59.136165661 +0000
 Birth: 2020-08-18 06:57:06.768492334 +0000
Run Code Online (Sandbox Code Playgroud)

幸运的是,对于较旧的系统,@whotwagner 编写了一个示例 C 程序,展示了如何statx(2)在 x86 和 x86-64 系统上使用系统调用。它的输出与stat的默认格式相同,没有任何格式选项,但修改它以仅打印出生时间很简单。

首先,克隆它:

git clone https://github.com/whotwagner/statx-fun
Run Code Online (Sandbox Code Playgroud)

您可以编译statx.c代码,或者,如果您只想要出生时间,请birth.c使用以下代码在克隆目录中创建一个(这是statx.c仅打印包含纳秒精度的创建时间戳的最小版本):

# stat --version
stat (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
# stat /
  File: /
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 88h/136d    Inode: 57279593    Links: 1
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-08-18 06:57:46.912243164 +0000
Modify: 2020-08-18 06:57:06.768492334 +0000
Change: 2020-08-18 06:57:59.136165661 +0000
 Birth: 2020-08-18 06:57:06.768492334 +0000
Run Code Online (Sandbox Code Playgroud)

然后:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这应该使创建时间更易于访问:

  • 应该支持更多的文件系统,而不仅仅是 ext* 文件系统(debugfs是用于 ext2/3/4 文件系统的工具,在其他文件系统上不可用)
  • 你不需要 root 来使用它(除了安装一些必需的包,比如makelinux-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: -
Run Code Online (Sandbox Code Playgroud)

但是,这对 NTFS 和 exfat 不起作用。我猜那些的 FUSE 文件系统不包括创建时间。


Luk*_*ski 6

TL; DR: 只需运行: sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

(要找出您的 fs,请运行df -T /path/to/your/file,很可能会是/dev/sda1)。

长版:

我们将运行两个命令:

  1. 找出文件的分区名称。

    df -T /path/to/your/file
    
    Run Code Online (Sandbox Code Playgroud)

    输出将如下所示(分区名称在前):

    Filesystem     Type 1K-blocks    Used Available Use% Mounted on
    /dev/<your fs> ext4   7251432 3481272   3509836  50% /
    
    Run Code Online (Sandbox Code Playgroud)
  2. 找出该文件的创建时间。

    sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
    
    Run Code Online (Sandbox Code Playgroud)

    在输出中,查找ctime.