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

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

当我尝试stat命令时,它表示Birth: -

那我怎样才能找到文件的创建时间?

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

  1. 通过ls -i命令知道目录的inode (比如说它的X

  2. 通过df -T /path命令知道你的目录保存在哪个分区(让我们说它在/dev/sda1

  3. 现在使用此命令: sudo debugfs -R 'stat ' /dev/sda1

您将在输出中看到:

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

crtime是文件的创建日期。

我测试了什么

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

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

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

@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文件或目录的创建日期:

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

stat无法显示创建时间是由于stat(2)系统调用的限制 ,其返回结构不包括创建时间的字段。 但是,从Linux 4.11(即17.10和更新版本*)开始, 新的statx(2)系统调用可用,其中包含返回结构中的创建时间。

*可能在使用硬件支持堆栈(HWE)内核的旧LTS版本上。 检查uname -r以查看您是否至少在4.11使用内核进行确认。

不幸的是,直接在C程序中调用系统调用并不容易。 通常,glibc提供了一个包装器,使工作变得简单,但glibc还没有为statx(2)添加包装器。 幸运的是,@ wwwwner写了一个示例C程序 ,展示了如何在x86和x86-64系统上使用statx(2)系统调用。 它的输出格式与stat的默认格式相同,没有任何格式化选项,但修改它只是为了打印出生时间很简单。

首先,克隆它:

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

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

 #define _GNU_SOURCE #define _ATFILE_SOURCE #include  #include  #include  #include  #include  #include "statx.h" #include  #include  #include  // does not (yet) provide a wrapper for the statx() system call #include  /* 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 *文件系统( 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: - 

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


如果,或者更确切地说,当glibc添加对statx(2)系统调用的支持时, stat将很快跟进,我们将能够使用plain old stat命令。 但是我不认为这会被反向移植到LTS版本,即使它们确实获得了更新的内核。 因此,我不希望任何当前版本 (14.04,16.04,17.04,17.10)的stat在没有人工干预的情况下打印创建时间。

TL; DR:运行: sudo debugfs -R 'stat /path/to/your/file' /dev/

(要计算你的fs,运行df -T /path/to/your/file ,很可能是/dev/sda1 )。

长版:

我们将运行两个命令:

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

     df -T /path/to/your/file 

    输出看起来像这样(分区名称是第一个):

     Filesystem Type 1K-blocks Used Available Use% Mounted on /dev/ ext4 7251432 3481272 3509836 50% / 
  2. 找出该文件的创建时间。

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

    在输出中,查找ctime