C++ 如何比较两个卷并列出修改过的文件?

C++ 如何比较两个卷并列出修改过的文件?,c++,winapi,backup,ntfs,volume,C++,Winapi,Backup,Ntfs,Volume,我有两个硬盘卷(一个是另一个的备份映像),我想比较这些卷并列出所有修改过的文件,以便用户可以选择要回滚的文件 目前,我正在递归新卷,并将每个文件的时间戳与旧卷的文件(如果它们是旧卷的整数)进行比较。显然,这是一种错误的做法。这既耗时又错误 有没有一种有效的方法 编辑: -我使用FindFirstFile,喜欢递归卷,并收集每个文件的信息(不是很慢,只需几分钟)。 -我正在使用卷影复制进行备份。 -备份卷是远程的,因此我无法连续监视实际卷。假设您没有将新卷上的每个文件与快照中的每个文件进行比较,这

我有两个硬盘卷(一个是另一个的备份映像),我想比较这些卷并列出所有修改过的文件,以便用户可以选择要回滚的文件

目前,我正在递归新卷,并将每个文件的时间戳与旧卷的文件(如果它们是旧卷的整数)进行比较。显然,这是一种错误的做法。这既耗时又错误

有没有一种有效的方法

编辑:
-我使用FindFirstFile,喜欢递归卷,并收集每个文件的信息(不是很慢,只需几分钟)。
-我正在使用卷影复制进行备份。

-备份卷是远程的,因此我无法连续监视实际卷。

假设您没有将新卷上的每个文件与快照中的每个文件进行比较,这是唯一的方法。在不查看所有文件的情况下,如何找到没有修改的文件?

我不是Windows程序员。 但是,您不应该使用stat函数来检索文件的修改时间。 根据mod time对文件进行排序。 mod time大于上次备份时间的文件是您感兴趣的文件

这是你第一次在备份卷上迭代,从你感兴趣的集合中计算出最大修改时间和创建时间。
我假设感兴趣的目录不会在备份卷中被修改

我没有等到更改发生后再扫描整个磁盘以查找(通常很少)已更改的文件,而是设置了一个程序,用于在更改发生时监视更改。这将使您能够以最少的麻烦和麻烦构建一个文件列表。

如果不知道您在这里要做什么,很难说。但是,关于我认为您正在努力实现的目标,有一些提示:

  • 如果您只关心NTFS卷,我建议查看USN/change journal API。自2000年以来,它们一直存在。这样,在初始库存之后,您只能查看从该点开始的更改。这是一个很好的起点,尽管这里有一篇非常古老的文章:
  • 此外,利用USNAPI,您可以省略散列步骤,只需自己记录日志中的信息(当您查看所述API时,这将变得更加清楚)
  • 第一次通过比较驱动器的内容,利用散列,如SHA-1或MD5
  • 将哈希和其他此类信息存储在某种数据库中。例如,SQLite3。请注意,这本身可能会占用大量空间。快速查看包含40k+文件的“我的音频”文件夹将获得约750兆的MD5信息

这部分取决于两卷的复制方式;如果从文件系统的角度来看它们是“真实”副本(例如卷影副本或其他块级副本),那么您可以对USN做一些棘手的小事情,这是其他人建议您研究的通用技术。例如,您可能想看看API。该API将允许您比较文件的两个不同副本(同样,假设它们是块级备份中具有相同文件参考号的同一文件)。如果您希望基本上是无状态的,这个API和类似的API将在这里对您有很大帮助。我的算法如下所示:

foreach( file in backup_volume ) {
    file_still_exists = try_open_by_id( modified_volume )
    if (file_still_exists) {
        usn_result = compare_usn_values_of_files( file, file_in_modified_volume )
        if (usn_result == equal_to) {
           // file hasn't changed at all
        } else {
           // file has changed (somehow)
        }
    } else {
        // file was deleted (possibly deleted and recreated)
    }
}
// we still don't know about files new in modified_volume
综上所述,我的经验让我相信,这将比我即兴的解释暗示的要复杂得多。不过,这可能是一个很好的起点

如果卷不是彼此的块级副本,那么比较USN编号和文件ID将非常困难,如果不是不可能的话。相反,您很可能会选择文件名,如果不打开每个文件(时间可以由应用程序修改,大小和时间可能在findfirst/next查询中过期,并且您必须处理已删除然后重新创建的案例、重命名案例等),这即使不是不可能也很难做到


因此,了解您对环境的控制程度非常重要。

这是我改用的方法(我使用旧快照获取新卷中每个文件的差异),但速度非常慢。我在想可能是在较低的级别(扫描和比较块还是什么?)@lalli:没有比
FindFirstFile
和friends更低级别(受支持)的API了。即使你打算自己解析磁盘上的NTFS格式,我也怀疑你能比Windows自己的NTFS.sys做得更快。要得到更有用的答案,你应该添加工具应该在哪个平台下运行。POSIX、win32还是别的什么?不同的平台具有不同的文件系统语义。很抱歉,现在添加了win32标记。谢谢你的消费?你是如何在卷中递归和比较的?我希望不是手工的。你熟悉脚本语言吗?Perl?校验和?我在windows的启动过程中很早就这样做了,所以环境的资源有限。我实现了MD5,计算一个卷的哈希值(大约350 GB已满)大约需要1.5个小时,如果不发生这种情况?我是否执行了错误的算法?请建议。谢谢。350GB MD5在1.5小时内就完成了,这不是不合理的——从磁盘上读取那么多数据可能需要那么长的时间。
stat
不是Windows函数。GetFileTime不应该做这项工作。如果你知道最大修改时间,你甚至不需要排序。您可以在当前卷的一次传递中获取列表。@user433874:No,
GetFileTime
需要一个文件句柄,这意味着您必须打开所有有问题的文件
FindFirstFile
和friends已经返回了您枚举目录的时间,所以我真的不明白您的观点。@Billy:如果有类似FindFirstFile的api可用,我不明白为什么只存储上一次备份时间并比较(上一次修改)会如此耗时