哪些操作应该更改目录的修改日期?

What operations should change the modification-date of a directory?

我正在编写一个可以备份或合并目录的工具。

文件的修改日期比较简单,但是目录的修改日期呢?

哪些操作被视为修改目录? (然后我会调用 OS 的 API 来做到这一点。)

根据操作系统和文件系统,预期语义有何不同? 它是否由常见的第 3 方程序持续更新?

常见的第 3 方程序是否依赖于目录修改日期的特定语义? (例如:增量备份程序是否递归到声明相同修改日期的目录中?)

加法:

这是另一个例子(尽管我希望范围更广): 当我将一个目录从一个驱动器复制到另一个驱动器时:实际发生的是,首先创建最外层的目录,然后递归地向下添加单个文件。添加的任何目录的最后一个条目将默认更改该目录的修改日期。结果是每个目录都有一个全新的修改日期,几乎没有信息价值(并且与源目录的修改日期不同)。一个问题是我们是否希望出现这种情况,或者我们是否希望随后将该目录的修改日期更改为与源驱动器上目录的修改日期相同。

很明显,当您意识到目录也是文件时,任何更改目录内容的内容都会更新其修改时间。由于 dir 的内容是文件名,基本上目录内的任何入口操作(create、mkdir、rmdir、unlink 等)都会更新其 mtime。您还可以使用 utime(2) 系统调用手动设置 atime 和 mtime。

所有这些都适用于 Linux 和各种 Unix 操作系统变体的文件系统。

您没有指定操作系统或文件系统,它们有不同的操作,因此为了便于说明,我们将采用 POSIX,到 "modification time" 我们将假设讨论是关于 mtime(而不是 ctime)。

POSIX 起源于 Unix,正如@itisravi 所说,目录只是另一种类型的文件。

这意味着两件事:

  • 每个更改文件的 mtime 并且可以在目录上调用的系统调用都可以更改目录的 mtime。
  • 每个修改目录 inode 数据内容的系统调用,即文件名列表或列表中与文件名关联的 inode 编号,都会更改目录的 mtime。

在第一类中我们有 utime(2) and it's variants such as futimens(2)

在第二类中我们有 creat(2), open(2) with O_CREAT, mkdir(2), mkfifo(2), mknod(2), bind(2) to a unix domain socket, rename(2), link(2), symlink(2), unlink(2), rmdir(2) 及其变体。

所有这些指向规范的链接都有相关部分说明何时必须更新 mtime。

他们没有的是关于mtime什么时候应该改变的任何规范。这意味着文件系统基本上可以随时将 mtime 更改为它想要的任何值。为什么要做这样的事情?这里有几个例子:

  • 后台任务,例如删除旧文件。
  • 管理员将文件系统恢复到旧快照。
  • 在不更新 mtime 的情况下无法有效地在后台优化或纠正错误的实施问题。
  • NFS silly rename(但请注意 NFS 不符合 POSIX)。

但是,在您正在编写的工具(rsync(1) 的克隆?)的上下文中,还有其他注意事项:

  • 元数据很重要。如果有人 chown 目录中的文件,它不会改变目录的修改时间,但你仍然需要进入目录并在那里做一些事情。
  • 一些工具,例如cp -a or Caja, 复制数据时会默认复制元数据。源数据的元数据确实比新建数据的元数据有用得多。
  • 合并目录时,您需要确定 mtime 设置的一致定义。可能 "the latest of the two directories" 是最普遍适用的定义。
  • 除了 rsync 之类的备份工具(听起来与您正在做的类似)之外,还有另一个对检测更改感兴趣的工具系列 - 构建工具。 make(1) also consider modification times, but that's "the old way", newer build tools hash the data they copy, and detect changes based on hashes 之类的工具 - 您可能需要考虑使用此选项。