如何在bash中比较80 md5sums

时间:2012-02-14 21:11:00

标签: linux algorithm bash

我必须将相同文件的80份副本的md5sums相互比较,并报告不匹配时的失败。我如何在bash中有效地做到这一点?我正在寻找一种优雅的算法来实现它。

3 个答案:

答案 0 :(得分:3)

md5sum FILES | sed 's/ .*$//' | sort -u

如果您获得多行输出,则表示您不匹配。

(这并不能告诉你哪里不匹配。)

将它组合在一起,并用一个稍微简洁的sed命令替换awk命令:

count=$(md5sum "$@" | awk '{print $1}' | sort -u | wc -l)
if [ $count -eq 1 ] ; then
    echo "Everything matches"
else
    echo "Nope"
fi

答案 1 :(得分:1)

输出:

md5sum $files | sort -k 1,2

是按排序顺序的校验和列表,后面是相应的文件名。如果你需要注意结果,这可能就足够了。如果您需要识别奇数球结果,您必须决定演示。你说你有80份“同一档案”。假设8个版本的'文件'实际上有10个副本。你怎么决定哪个是正确的,哪个是假的?如果你有41个有一个哈希而39个有另一个哈哈怎么办?你确定39是错的而且41是正确的吗?很明显,一个哈希可能会占主导地位,但你必须担心那些讨厌的边界条件。

你也可以做更好的事情,例如:

md5sum $files | sort -k 1,2 > sorted.md5
sed 's/ .*//' sorted.md5 | uniq -c | sed 's/^ *\([0-9][0-9]*\) \(.*\)/\2 \1/' > counted.md5
join -j 1 -o 1.1,2.2,1.2 sorted.md5 counted.md5

这将为您提供包含MD5校验和,重复计数和文件名的输出。如果您愿意,可以使用sed替换第一个awk '{print $1}'脚本。第二个将被awk '{printf "%s %s\n", $2, $1}'取代,这可能更清晰( 更短)。这个充满希望的原因是摆脱uniq -c输出中的前导空格,这会混淆join

md5sum $files | sort -k 1,2 > sorted.md5
awk '{print $1}' sorted.md5 | uniq -c | awk '{printf "%s %s\n", $2, $1}' > counted.md5
join -j 1 -o 1.1,2.2,1.2 sorted.md5 counted.md5

我通过复制dbatools.h创建了一些文件x1.h,x2.h和x3.h,并设置了files=$(ls *.h)。输出是:

0763af91756ef24f3d8f61131eb8f8f2 1 dblbac.h
10215826449a3e0f967a4c436923cffa 1 dbatool.h
37f48869409c2b0554d83bd86034c9bf 4 dbatools.h
37f48869409c2b0554d83bd86034c9bf 4 x1.h
37f48869409c2b0554d83bd86034c9bf 4 x2.h
37f48869409c2b0554d83bd86034c9bf 4 x3.h
5a48695c6b8673373d30f779ccd3a3c2 1 dbxglob.h
7b22f7e2373422864841ae880aad056d 1 dbstringlist.h
a5b8b19715f99c7998c4519cd67f0230 1 dbimglob.h
f9ef785a2340c7903b8e1ae4386df211 1 dbmach11.h

这可以根据需要进一步处理(例如,使用sort -k2,3nr以递减顺序获取计数,因此异常文件最后出现)。您可以将重复文件的名称组合在一起,并附上一个计数,告诉您每个重复的数量。你接下来做什么取决于你。

当然,真正的生产脚本会使用临时文件名而不是硬编码名称,并且会自行清理。

答案 2 :(得分:0)

md5sum FILES > MD5SUMS.md5
cut -c1-32 < MD5SUMS.md5 | sort | uniq -c | sort -n 

会返回这样的内容:

  1 485fd876eef8e941fcd6fc19643e5e59
  1 585fd876eef8e941fcd6fc19643e5e59
  5 385fd876eef8e941fcd6fc19643e5e59

阅读:5个文件具有相同的校验和,另外两个具有“单独”校验和。我认为,大多数是正确的,所以另外一个

| tail -1 | cut -c 9-

返回最后一行的校验和。现在过滤其他所有内容(并将各部分放在一起):

md5sum FILES > MD5SUMS.md5
grep -v "$(cut -c1-32 < MD5SUMS.md5 | sort | uniq -c | sort -n | tail -1 | cut -c 9-)" MD5SUMS.md5 | cut -c35- 

这将打印非多数文件的文件名。