我正在编写一些内容,通过散列其内容样本来汇总文件系统中的文件。它构造了一个目录和文件树。每个文件条目都具有文件内容的哈希值。对于每个目录条目,我想存储目录中所有文件内容的哈希值,包括子目录中的那些 - 我将其称为目录内容哈希。
关于目录内容哈希的棘手问题是我希望它独立于目录的结构。 I.E.如果两个目录包含相同的文件,但是使用不同的子目录结构进行组织,则哈希应该相同。
我能想到的唯一两种方法是:
计算所有文件内容哈希值的串联的MD5。为了获得所需的哈希属性,我必须列出目录中的所有文件,按哈希对它们进行排序,连接已排序的哈希值,然后在串联上运行MD5。这似乎比我想要的慢。在计算整个树中的目录内容哈希时,我可以通过使用合并排序非常有效地进行排序,但我无法在大输入上计算大量MD5哈希值。
使用XOR合并文件内容哈希。每个目录只需要对其直接子节点的文件内容哈希和目录内容哈希进行异或。这非常快速和简单,但不是非常抗冲击。它甚至无法区分包含1个文件实例的目录和包含同一文件的3个实例的目录。
如果有一个函数可以使用类似于方法#2中使用XOR的方式,那就更好了,但更具抗冲突性。我认为方法#1对于这个具体案例来说足够快,但为了探索所有选项/知识好奇心/未来应用程序,我想知道是否有一个满足描述的函数标题(我有一个模糊的记忆,想要过去几次想要这样的功能)。
感谢。
答案 0 :(得分:5)
对哈希集合进行独立哈希处理(基本上是你正在寻找的,非?)
听起来任何与顺序无关的操作(如加法或乘法)都可以帮到你。增加的好处是以一种很好的方式溢出。我不记得乘法是否也会起作用。
简而言之:添加所有值,忽略溢出,你应该得到一些有用的东西。如果添加不足以抵抗碰撞,任何其他类似的功能都应该起作用。
答案 1 :(得分:4)
由于物品数量很重要但订单不重要;只需对哈希列表进行排序,然后对列表进行哈希处理。
find . -print0 | xargs -0 sha1sum | cut -c -40 | sort | sha1sum
这将给出对目录排列不变的哈希值类型。
答案 2 :(得分:0)
如果你有谷歌番石榴可用,它提供了一个实用工具方法,Hashing.combinedUnordered(),它可以做你想要的。 (在内部,这是通过将所有哈希加在一起来实现的。)
https://code.google.com/p/guava-libraries/wiki/HashingExplained
答案 3 :(得分:0)
我找到了这篇文章:https://kevinventullo.com/2018/12/24/hashing-unordered-sets-how-far-will-cleverness-take-you/
就像@Slartibartfast 所说的,添加就是你想要的。这篇文章的有趣之处在于,它证明了无论你做什么“可交换”操作,总会有问题元素。在加法的情况下,问题元素是哈希值为0的项。
<块引用>虽然有几种定义散列的文档方法 迭代顺序为列表和其他容器的函数 保证,关于最佳实践的讨论似乎较少 用于为无序容器定义哈希函数。一明显 方法是简单地将 {(+)} 或 xor {(\oplus)} 的哈希相加 容器的各个元素。这些方法的缺点 是否存在散列为 0 的“问题元素”;当这样的 元素被插入到任何容器中,该容器的哈希值将 维持不变。人们可能会怀疑这是由于结构化 加法或异或的性质,以及更聪明的哈希选择 无序容器上的函数可以避免这种情况。事实上,在 文章的结尾,我们将用数学方法证明一个命题 粗略地说,任何用于散列无序的通用方法 容器,可以基于现有的增量更新 hash,本质上等同于更“明显”的选择之一 因为它具有相同的代数结构,特别是具有 相同的“问题”元素。