如何使用bash删除重复文件


10

我有一个包含重复文件的文件夹md5summd5在Mac上,按(在Mac上)文件),我想要一个 计划删除所有找到的作业。

但是,我仍然坚持如何执行此操作。到目前为止,我有:

md5 -r * | sort

输出如下内容:

04c5d52b7acdfbecd5f3bdd8a39bf8fb gordondam_en-au11915031300_1366x768.jpg
1e88c6899920d2c192897c886e764fc2 fortbourtange_zh-cn9788197909_1366x768.jpg
266ea304b15bf4a5650f95cf385b16de nebraskasupercell_fr-fr11286079811_1366x768.jpg
324735b755c40d332213899fa545c463 grossescheidegg_en-us10868142387_1366x768.jpg
3993028fcea692328e097de50b26f540 Soyuz Spacecraft Rolled Out For Launch of One Year Crew.png
677bcd6006a305f4601bfb27699403b0 lechaustria_zh-cn7190263094_1366x768.jpg
80d03451b88ec29bff7d48f292a25ce6 ontariosunrise_en-ca10284703762_1366x768.jpg
b6d9d24531bc62d2a26244d24624c4b1 manateeday_row10617199289_1366x768.jpg
ca1486dbdb31ef6af83e5a40809ec561 Grueling Coursework.jpg
cdf26393577ac2a61b6ce85d22daed24 Star trails over Mauna Kea.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x768.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x7682.jpg

如何根据文件的MD5进行处理以删除重复项?我并不在乎我保留哪个 “原始”字符,但我只想保留一个。

我是否应该以其他方式来处理这个问题?


3
已经有一个fdupes命令可以执行此操作了。。。不确定您使用的是哪个发行版,但是在同名的Debian软件包中。而且,如今MD5的哈希值还比较弱。您可能想使用sha256sum 或更佳的设备sha512sum(实际上在普通的PC硬件上应该会更快
derobert

1
@derobert-我知道MD5是一个弱哈希,但是它比较简单,足以用于比较小文件:)
沃伦

好吧,MD5冲突是已知的并且可以以相当适度的CPU能力生成,并且可以替换为使用SHA-512的命令,所以……
derobert 2015年

@derobert-我知道使用md5有潜在的负面影响..但是在这种情况下,这已经足够了(希望确保我在给定的目录中没有重复的文件)
沃伦

1
很公平。评论的重点是指出fdupes。
derobert 2015年

Answers:


3

我正在Linux上工作,这意味着md5sum输出的命令是:

> md5sum *
d41d8cd98f00b204e9800998ecf8427e  file_1
d41d8cd98f00b204e9800998ecf8427e  file_10
d41d8cd98f00b204e9800998ecf8427e  file_2
d41d8cd98f00b204e9800998ecf8427e  file_3
d41d8cd98f00b204e9800998ecf8427e  file_4
d41d8cd98f00b204e9800998ecf8427e  file_5
d41d8cd98f00b204e9800998ecf8427e  file_6
d41d8cd98f00b204e9800998ecf8427e  file_7
d41d8cd98f00b204e9800998ecf8427e  file_8
d41d8cd98f00b204e9800998ecf8427e  file_9
b026324c6904b2a9cb4b88d6d61c81d1  other_file_1
31d30eea8d0968d6458e0ad0027c9f80  other_file_10
26ab0db90d72e28ad0ba1e22ee510510  other_file_2
6d7fce9fee471194aa8b5b6e47267f03  other_file_3
48a24b70a0b376535542b996af517398  other_file_4
1dcca23355272056f04fe8bf20edfce0  other_file_5
9ae0ea9e3c9c6e1b9b6252c8395efdc1  other_file_6
84bc3da1b3e33a18e8d5e1bdd7a18d7a  other_file_7
c30f7472766d25af1dc80b3ffc9a58c7  other_file_8
7c5aba41f53293b712fd86d08ed5b36e  other_file_9

现在使用awkxargs命令将是:

md5sum * | \
sort | \
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
xargs rm

awk部分lasthash使用空字符串初始化,该字符串将不匹配任何哈希,然后检查每一行中的哈希lasthash是否与当前文件(第二列)的哈希(第一列)相同。如果是,它将打印出来。在每个步骤的最后,它将设置lasthash为当前文件的哈希值(您可以将其限制为仅在哈希值不同时才设置,但这应该是一件小事,尤其是当您没有很多匹配文件时)。该文件名的awk吐出被送到rmxargs,基本上调用rm什么的awk一部分给了我们。

您可能需要先过滤目录md5sum *

编辑:

使用Marcins方法,您也可以使用以下一种方法:

comm -1 -2 \
  <(ls) | \
  <(md5sum * | \
    sort -k1 | \
    uniq -w 32 | \
    awk '{print $2}' | \
    sort) \
xargs rm

减去文件列表,该文件列表由ls所包含的每个唯一哈希的第一个文件名所包含md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'


1
谢谢:md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rm是OS X上的电话(根据@ Stephen Kitt的建议,echo 'will remove '在尝试之前,我在结尾处放了一个rm
沃伦

然后,您可能应该编辑问题,因为给定的解决方案与您给出的示例输出不匹配。
Stephen Kitt 2015年

1
并且您应该更改sort -t ' ' -k 4 -rsort
Tristan Storch 2015年

@TristanStorch-好地方:)
沃伦

这假设您的文件名中没有空格,在任何情况下都是危险的假设。(特别是考虑到OP使用的是Mac。我敢于您找到Mac,任何Mac,都没有包含空格的文件名。):)
通配符

7

您可以使用以下命令识别重复的文件:

md5sum * | sort -k1 | uniq -w 32 -d

1
每组重复项仅输出一个文件。如果要删除所有重复项并仅保留一个重复项,则可以保留通过此命令获得的重复项,然后删除其余重复项
golimar

2

我遇到了fdupes来回答这个类似的问题:https : //superuser.com/questions/386199/how-to-remove-duplicated-files-in-a-directory

我能够apt-get install fdupes在Ubuntu上使用。您肯定会想要阅读手册页。就我而言,我能够获得所需的结果,如下所示:

fdupes -qdN -r /ops/backup/

上面写着“递归查看/ ops / backup并找到所有重复的文件:保留任何给定文件的第一个副本,然后静静地删除其余文件。” 这使得保留不经常写入的数据库的多个转储非常容易。


1

如果您很着急(或者您有很多文件)并且想要避免排序的开销(这需要时间),但是不要在意哈希表的内存开销(或者您的内存中有很多内存)的文件),

find . -type f -print0 | xargs -0 md5sum | awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }' | xargs -0 rm

find . -type f -print0:查找所有文件并使用以空值结尾的名称输出它们

xargs -0 md5sum:并行计算哈希值(根据需要调整-nmax-args和-Pmax-procs,请参阅man xargs

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }':如果awk哈希表中有一个包含我们当前正在查看的md5sum的条目,则打印出我们当前正在查看的文件名,以空值结尾。否则,将文件名添加到哈希表。

xargs -0 rm:采用管道输入的空终止字符串并将其发送给rm。

这比fdupes快得多。

如果您的文件名包含换行符,则awk可能会在换行符处截断该文件名,因为md5sum也会通过换行符分隔记录。

这是基于/programming/11532157/remove-duplicate-lines-without-sorting/programming/9133315/how-can-i-output-null-terminated-弦乐


1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. 取所有md5值
  2. 对它们进行排序,以便对uniq进行重复
  3. 运行uniq只输出双倍
  4. 从带有md5值的行中剪切文件名
  5. 反复调用文件名上的删除

0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

特征:

  • 如果每个文件重复一个以上,则仍然有效
  • 如果文件名带有空格,则仍然有效
  • 如果您使用别名ls--color=always
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.