【问题标题】:Has Directory Content Changed?目录内容是否已更改?
【发布时间】:2013-11-11 19:22:30
【问题描述】:

如何检查目录以查看其内容自给定时间点以来是否已更改?

我不需要通知我什么时候它改变了,或者什么改变了。我只需要一种方法来检查如果它已经改变了。

【问题讨论】:

  • 将该目录复制到另一个地方,然后他们进行比较。或者只检查mtime 的文件。
  • 这是一个充满大型资产的目录,因此复制它不是一种选择。所以没有指示更改的目录属性?我需要递归检查所有文件和子目录并比较存在性和mtime?
  • 下面的解决方案应该可以工作。只需将递归 glob() 调用的哈希值存储并比较到相关目录即可。

标签: ruby macos file directory


【解决方案1】:

在您希望开始监控的时间点创建一个文件,使用您喜欢的任何方法,例如:

touch time_marker

然后,当您要检查是否添加了任何内容时,请像这样使用“查找”:

find . -newer time_marker

这只会告诉您自 time_marker 创建以来已修改或添加的文件 - 它不会告诉您是否已删除任何内容。如果您想再次查看未来点,请再次“触摸”time_marker 以创建新的参考点。

【讨论】:

    【解决方案2】:

    如果您只需要知道名称是否已更改或文件是否已添加/删除,您可以试试这个:

    Dir.glob('some_directory/**/*').hash
    

    只需存储和比较哈希值。显然,您可以通过调用 ls 或从代表目录结构中每个文件的 File 对象中获取更多信息并对其进行散列处理,从而更进一步。

    Dir.glob('some_directory/**/*').map { |name| [name, File.mtime(name)] }.hash
    

    UM ACTUALLY 我很笨,哈希仅对任何一个 ruby​​ 运行时环境都是一致的。让我们改用标准的Zlib::crc32,例如

    Zlib::crc32(Dir.glob('some_directory/**/*').map { |name| [name, File.mtime(name)] }.to_s)
    

    我担心的是,如果您正在检查一个非常大的文件系统,这种方法会占用大量内存并且速度很慢。也许通配整个结构并对其进行映射不是这样 - 如果您有很多子目录,您可以递归地遍历它们并为每个子目录计算校验和,然后组合校验和。

    这对于较大的目录可能会更好:

    Dir.glob('some_directory/**/*').map do |name| 
      s = [name, File.mtime(name)].to_s
      [Zlib::crc32(s), s.length]
    end.inject(Zlib::crc32('')) do |combined, x| 
      Zlib::crc32_combine(combined, x[0], x[1])
    end
    

    这将不太容易发生冲突:

    Dir.glob('some_directory/**/*').map do |name| 
      [name, File.mtime(name)].to_s
    end.inject(Digest::SHA512.new) do |digest, x| 
      digest.update x
    end.to_s
    

    【讨论】:

    • 这很棒。谢谢。
    • 我发现这种方法存在一些奇怪的不一致之处。如果我打开 IRB 并重复执行Dir.glob('some_directory/**/*').map { |name| [name, File.mtime(name)] }.hash,我每次都会得到相同的值。但是,如果我关闭 IRB,重新打开并再次执行相同操作,我会得到不同的值(再次重复)。
    • 抱紧,我会调查的。我认为哈希对于任何给定的输入都是一致的。
    • 好的,我们需要生成一个 CRC 摘要。对于任何给定的运行时环境,散列只需要保持一致。 (这就是我喜欢在 Stack Overflow 上解决问题的原因。)
    • 工作如梦。非常小的目录结构,所以没有性能问题。感谢您的帮助。
    【解决方案3】:

    我已对此进行了修改以包括时间戳和文件大小。

    dir_checksum = Zlib::crc32(Dir.glob(
      File.join(dispatch, '/**/*')).map { |path|
        path.to_s + "_" + File.mtime(path).to_s + "_" + File.size(path).to_s
      }.to_s)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-22
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 2010-11-04
      • 2014-11-17
      • 2023-04-10
      • 1970-01-01
      相关资源
      最近更新 更多