我想在C ++中找到文件系统上的重复文件。有没有算法尽快做到这一点?我是否需要创建一个多线程应用程序,或者我只能使用一个线程来完成它?
答案 0 :(得分:10)
我同意Kerrek SB的说法,有比C ++更好的工具,但是,假设你真的需要在C ++中这样做,这里有一些建议和要在你的实现中考虑的事项:
使用boost :: filesystem进行可移植文件系统遍历
散列每个文件建议都非常合理,但首先制作文件大小为关键的多重映射可能更有效。然后仅在存在重复大小的文件时应用哈希。
决定如何处理空文件和符号链接/捷径
决定了您希望如何处理特殊文件,例如:在unix上你有目录fifos,socket等
说明在算法运行时文件或目录结构可能会发生变化,消失或移动的事实
说明某些文件或目录可能无法访问或损坏(例如递归目录链接)
使线程数可配置为有意义的并行化数量取决于底层磁盘硬件和配置。如果你是一个简单的硬盘驱动器而不是昂贵的san,那将会有所不同。但是,不要做出假设;测试一下。例如,Linux非常适合缓存文件,因此很多读取都来自内存,因此不会阻塞i / o。
答案 1 :(得分:8)
1)不要使用C ++。您需要的所有工具都已存在。
2)散列每个文件(例如使用md5sum
)并构建文件名,文件大小和哈希值的索引。*
3)按哈希值排序并查找重复的哈希值和大小对(例如,使用sort
)。
4)对候选人重复做一个普通的diff
。
您可以通过一些工作来并行化步骤2),但您将受到存储的I / O速度的限制。您可以通过将大型索引文件拆分为位,对它们进行单独排序然后合并它们来并行化步骤3)(<{1}})。
*)正如@frankc所说,实际上不要散列每个文件,而只是那些大小不唯一的文件。从基于 size 的索引开始。你需要散列很多小文件,但只有很少的大文件。
答案 2 :(得分:4)
我会这样做:
multimap
中,文件大小为索引; multimap
桶,即大小唯一的文件;那些肯定不能重复。multimap
,其中哈希为键,路径为值)。这个过程应该比盲目地散列所有文件快得多,因为大多数文件都有不同的大小,只要看一下就可以分开;并且检查文件大小比散列文件便宜得多,因为它只是一个文件系统属性查找而不是读取文件的整个内容。
需要最后一步,因为可能存在具有相同散列的不同文件;但是由于具有良好的散列函数,大部分工作已经完成,因为不相关文件的散列冲突应该非常少见。
请注意,您的哈希函数不需要加密安全,也不需要特别快(我想这个过程的时间将由IO控制)。
此外,由于您实际上不需要有一个已排序的容器,而不是multimap
,您可以使用unordered_multimap
,因为它应该有更快的查找时间,一旦您知道有多少您必须处理的文件,您可以使用明确的最大元素数调用reserve
,避免重新分配。