我有一个文件 data.txt,它被分成多个片段。我需要正确组合文件片段,以便创建原始文件 data.txt。我不知道什么程序会执行此操作,因为片段的名称没有层次结构。但我有一个md5sum
文件 data.txt (其中列出了片段)。如何使用该md5sum
文件从其碎片恢复整个文件?
答案1
perl -MAlgorithm::Combinatorics=permutations \
-le '$i=permutations(\@ARGV); while ($p=$i->next) { $n++; print "combo$n @$p" }' frag1 frag2 frag3 frag4 \
| while read out a b c d; do cat $a $b $c $d > $out; md5 $out; done
或者,如果您有 GNU 工具,则md5sum
可以代替。md5
答案2
有多少个碎片?听起来您必须尝试片段的每一种排列(或者直到找到正确的排列),因此即使解决相对少量片段的问题也会导致大量的工作。
答案3
了解一部分的校验和无助于计算整体的校验和,因此您必须计算所有可能排列的校验和,直到找到正确的排列。如果你有n部分,有n! (阶乘n)排列,如果它们的可能性相同,你就必须处理n平均 !/2,直到找到合适的为止。
当需要计算具有相同前缀的多个字符串的校验和时,可以通过存储MD5函数的内部状态来节省时间。例如,对于三个部分(X、Y、Z),您需要计算 MD5(X+Y+Z)、MD5(X+Z+Y)、MD5(Y+X+Z)、MD5(Y +Z+X)、MD5(Z+X+Y) 和 MD5(Z+Y+X)。如果开始计算 MD5(X,…),则复制状态并完成后缀 Y+Z 和 Z+Y 的计算。但您需要的是内部状态,而不是输出,并且大多数工具不允许访问内部状态。
蟒蛇的哈希库提供了一种copy
复制哈希函数内部状态的方法。它还有一个枚举排列的迭代器在其标准库中。
#!/usr/bin/env python2
import hashlib, itertools, sys
def look_for_permutation(goal, filenames):
n = len(filenames)
files = map(open, filenames)
previous = map(lambda _: None, filenames)
states = [hashlib.md5()] + [None] * (n-2)
for current in itertools.permutations(files):
i = 0
while current[i] == previous[i]:
i += 1
state = states[i].copy()
for f in current[i:n-2]:
state.update(f.read())
i += 1
states[i] = state.copy()
f.seek(0)
state.update(current[n-2].read())
current[n-2].seek(0)
state.update(current[n-1].read())
if state.hexdigest() == goal:
return current
current[n-1].seek(0)
previous = current
return None
if __name__ == '__main__':
result = look_for_permutation(sys.argv[1], sys.argv[2:])
if result:
for f in result: print f.name
sys.exit(0)
else:
sys.exit(1)
该脚本优化了哈希计算,但重复读取文件内容。如果文件内容适合内存,您可以通过一次性加载文件来加快速度。