在shell中删除具有相同md5sum的文件

Delete files with same md5sum in cshell

我正在尝试执行一项检查,其中所有具有相同 md5sum 的文件将被删除,保留第一次出现。

输入:第一列是md5值,第二列是文件名。

ab331f253704b84ae0aa5606adce4e7d  1.tcl              
ab331f253704b84ae0aa5606adce4e7d  2.tcl             
d86bbfda16f0d63ba35945e09dddce4d  3.tcl            
1d0b140d16d32d2adbaa15643bdba412  4.tcl            
8c97ae7965ae44ca6a4000d4e5988d54  5.tcl             
ddf373efda3bbdf83d2dfa9cb7fc4d96  6.tcl                  
1d0b140d16d32d2adbaa15643bdba412  7.tcl               
ddf373efda3bbdf83d2dfa9cb7fc4d96  8.tcl

输出:执行 rm -rf 2.tcl 7.tcl 8.tcl 因为存在具有相同 md5sum 的其他文件。

ab331f253704b84ae0aa5606adce4e7d  1.tcl             
d86bbfda16f0d63ba35945e09dddce4d  3.tcl               
1d0b140d16d32d2adbaa15643bdba412  4.tcl                           
8c97ae7965ae44ca6a4000d4e5988d54  5.tcl            
ddf373efda3bbdf83d2dfa9cb7fc4d96  6.tcl

你有什么问题?算法或在 csh 中实现它?

如果您不寻求超快的操作,朴素的算法很简单:

在伪语言中:

for srcfile in sorted(list_of_files):
  for tgtfile in list_of_files:
    if srcfile != tgtfile and md5(srcfile) == md5(tgtfile):
      delete tgtfile

我假设您的目标是从文本输入中删除某些行,而不是实际删除文件。

像这样:

awk '! seen[]++'

这是从标准输入读取的。如果输入在文件中,你可以这样做:

awk '! seen[]++' inputfile.txt

或者,如果它是某个命令的输出:

some_command | awk '! seen[]++'

说明:seen是一个关联数组。 </code> 是当前行的第一个以空格分隔的字段。 <code>awk 逐行处理输入。 seen[] 告诉你当前行的第一个字段以前是否看过; ++ 递增该值,将当前行标记为已在您下次看到时看到。递增一个不存在的数组元素将其设置为 1.

这假设您的系统上安装了 awk。你可能会。

如果您正在寻找纯 csh 的解决方案,而不调用外部命令,那将更加困难(而且我想不出这样做的充分理由)。


显然你真的想删除这些文件。这是一个解决方案:

awk '{ md5sum = ; file = ; if (seen[md5sum]++) { print "rm", file } }'

同样,您需要为此命令提供所需的输入。

这会打印但不会执行一系列 rm 命令。例如,给定问题的输入,输出为:

rm 2.tcl
rm 7.tcl
rm 8.tcl

您可以修改 awk 命令以使用 system("rm " file") 而不是仅打印它,但为了增加安全性,我会将输出写入文件,检查它看起来是否正确,然后source 删除文件的文件。使用根据任意输入自动删除文件的脚本很容易搬起石头砸自己的脚。