Linux下修改文件时间戳最直接可靠的方式是touch命令,支持单独设置atime(-a)或mtime(-m),用-t指定格式化时间(如202201011234),-d支持自然语言和Unix时间戳,但ctime不可手动修改。

Linux 下修改文件时间戳最直接、最可靠的方式就是用 touch 命令——它不依赖外部工具,系统自带,且支持精确控制访问时间(atime)、修改时间(mtime)和状态变更时间(ctime)中的前两者(注意:ctime 无法手动设置,它由内核自动更新)。
如何只改访问时间(atime)或只改修改时间(mtime)
默认情况下 touch 同时更新 atime 和 mtime。若只想改其一,必须显式指定:
- 仅更新访问时间:
touch -a file.txt - 仅更新修改时间:
touch -m file.txt - 两者都更新(等价于不加参数):
touch file.txt
注意:-a 和 -m 可以一起用,但效果和默认行为一样;单独使用才能实现“只改一个”的目的。实测中容易误以为 touch -a 会保留原 mtime,结果发现没生效——那大概率是文件系统挂载时用了 noatime 或 relatime 选项,此时 -a 会被内核忽略。
如何把时间戳设为指定日期(比如 2022-01-01 12:34)
用 -t 参数传入严格格式的时间字符串:touch -t 202201011234.00 file.txt。格式是 [[CC]YY]MMDDhhmm[.ss],年份可省略前两位(即 2201011234 等效),秒可省略(末尾的 .00 可不写)。
常见翻车点:
- 写成
2022-01-01 12:34——touch不解析带符号或空格的格式,会报错invalid date format - 时区未考虑:该时间默认按系统本地时区解释,不是 UTC。如果脚本要跨时区运行,建议先用
TZ=UTC touch -t ...显式指定 - 纳秒级精度不可设:
touch最小单位是秒,.00是占位符,不能填.123
如何批量修改多个文件的时间戳并保持相对顺序
比如想让目录下所有 .log 文件的时间戳按文件名排序后依次递增 1 秒,可以用 shell 循环配合 -d 参数:
seconds=1672531200 # 起始 Unix 时间戳,对应 2023-01-01 00:00:00 for f in *.log; do touch -d "@$seconds" "$f" ((seconds++)) done
-d 比 -t 更灵活,支持自然语言("yesterday"、"3 hours ago")、ISO 格式("2023-01-01T12:00:00")和 Unix 时间戳(@1672531200)。但要注意:-d 在部分老旧系统(如 CentOS 6 的 GNU coreutils -t + 字符串拼接。
为什么 touch 后 ls -l 看不到 ctime 变化
因为 ctime(change time)记录的是 inode 元数据最后一次被修改的时间,包括权限、所有者、链接数等变更。而 touch 即使只改 atime/mtime,也会触发 ctime 更新——所以你一定看到了变化,只是 ls -l 默认不显示 ctime。要用 stat file.txt 查看完整时间字段,其中 Change: 行才是 ctime。另外,某些文件系统(如 ext4 mounted with noatime)在更新 atime 时可能跳过 ctime 更新,这是内核优化行为,非 bug。










