根据手册页touch
,为了更改符号链接上的时间戳,可以使用touch -h -t MMDDhhmm mylink
.
这在我的带有 APFS 的 macOS 机器上不起作用,链接的时间戳未修改,并touch
按照链接修改目标的时间戳。
这是关于 APFS 的已知事实还是有什么我不明白的?
您似乎在 macOS 中发现了一个错误。操作系统的倒数第二个主要版本根据手册页运行,但最新版本不运行。
手册页已过时,或者软件存在错误(很可能)。
您可以在这里以普通用户的身份向 Apple 发送反馈:'
https://www.apple.com/feedback/macos.html
或者,如果您是开发人员,您可以使用反馈助手来提交错误报告,如下所述:
https://developer.apple.com/bug-reporting/
Apple目前没有touch
可用的更新版本,因此您无法通过升级来解决问题。正如您自己指出的那样,您可以改用 GNU 版本touch
来完成工作。你可以在 Homebrew 中安装coreutils
.
GNU 版本touch
通过调用较新的futimens()
/utimensat()
函数来工作(在后一种情况下,flag
参数设置为AT_SYMLINK_NOFOLLOW
更改链接本身的时间戳)。
touch
(287.100.2)的 Catalina 版本通过调用旧lutimes()
函数来工作,该函数显式设置链接本身的时间戳。新旧 API 之间的核心区别之一是新 API 支持以纳秒为单位的时间戳,而旧 API 的分辨率较低。
Big Sur 上的lutimes()
函数本身并没有实现系统调用,而是完全包含在标准库中,使用该setattrlist()
函数(导致系统调用)实际执行文件系统修改。setattrlist()
高度依赖文件系统(即它在 HFS+ 文件系统上的工作方式与它在 APFS 文件系统上的工作方式不同)。
touch
(321.100.11)的 Big Sur 版本通过setattrlist()
直接调用函数来工作,并且只有在调用失败时才回退到lutimes
. 不幸的是,程序员似乎忘记了需要指定何时-h
指定,修改必须在链接本身上进行。
实际的错误在 touch.c 的第 219 行,其中这一行:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), 0))
本来应该:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), utimes_f == lutimes ? FSOPT_NOFOLLOW : 0))
你可以在 touch.c 中改变它,重新编译它,然后得到一个可以工作的二进制文件。
答案是:touch
macOS 捆绑的默认不能更改时间戳,但从touch 8.32
可以GNU coreutils
...
有趣的是,2021 BSD 版本的 touch 也有同样的问题,并没有正确处理-h
标志。