很多Linux用户都曾遇到过这样一个问题:想用stat命令查看文件的创建时间,结果发现要么为空,要么显示一个-,更麻烦的是,系统有时会把修改时间(ctime)直接当成创建时间填进去。这并不是你操作有误,而是底层文件系统压根就没有保存这个字段。

简单来说,stat命令在默认输出中,那个Birth字段要么是空的,要么直接显示一个-,更令人困惑的是,在某些场景下它会将ctime(inode change time)伪装成创建时间。这个责任主要在于Linux内核以及主流的ext4、XFS等文件系统——它们天生就没有保存crtime(creation time)这一信息。
哪些文件系统真的支持crtime?
真正能够通过stat命令如实返回crtime的文件系统其实非常有限。以下情况属于例外:
- btrfs:前提是启用了
inode_cache,并且挂载时带有相应选项。好在较新的内核版本默认已经开启,这时stat可以正确显示Birth字段。 - XFS:要求则更多。内核版本必须达到5.10及以上,文件系统格式需为v5(这基本取决于当初格式化时的参数),同时挂载时要启用
inode64或默认行为符合条件。最可靠的验证方式是使用xfs_info查看,确认输出中是否包含“feature: crtime”。 - apfs(macOS专属)、NTFS(通过
ntfs-3g挂载并开启crtime选项)等,在原生Linux环境下几乎没有参考价值。
执行stat /path/to/file后,如果看到Birth字段显示-或—,基本可以断定你的文件系统不支持这个字段。
为什么“Birth”字段经常不可信?
即便stat真的打印出了一个时间,也别高兴得太早——它很可能是假的:
- ext4文件系统自始至终都不保存crtime,但像RHEL 8+/CentOS 8+这些发行版,为了兼容POSIX工具链,干脆让
stat把ctime(即inode change time)填入Birth字段中。这不是bug,而是刻意设计。 - 旧版的
coreutils(stat所属的包)在缺乏crtime支持时会直接留空,而新版本则悄悄fallback到ctime,却很少在文档中明确说明。 - 在容器或者overlayfs层中,宿主机文件系统本来就不支持crtime,上层再怎么调用
stat都是徒劳。
自行验证很简单:执行stat -c "%z %w" /path,它会分别输出ctime和Birth。如果两个值完全一致,那基本上就是伪造的。
真想查文件诞生时间?别指望stat
在标准的Linux环境下,并没有一个通用且可靠的方法来获取文件的原始创建时间。如果真的需要,有几个途径可以尝试,但都不算完美:
- 如果你使用btrfs并且确认启用了crtime,可以用
stat -c "%w" /file直接读取Birth字段。但必须先用lsattr /file和sudo debugfs -R "stat交叉验证——注意,ext4下debugfs是不会输出crtime的。" /dev/sdXN - 依赖日志:如果
auditd提前配置了规则,例如-a always,exit -F arch=b64 -S openat -F success=1 -k file_create,那么事后可以用aureport -k file_create查到。但前提是你一开始就考虑到了这一步。 - 依靠备份或版本控制系统:Git的提交记录、rsync的日志、restic的快照(
restic snapshots --json)等,其实比文件系统本身更加可靠。它们记录的“创建时间”才是真正意义上的时间点。
最后需要坦白说——在大多数生产环境中,“文件创建时间”本身就是一个语义模糊的概念。mv、cp、tar解包、甚至编辑器另存为新文件,都有可能造成创建时间被覆盖或重置。真正有审计需求,必须从源头设计日志采集,而不是指望stat突然变出魔法来。
