在UNIX系统中删除相同的文件

3

我正在处理大量(30,000)大小约为10MB的文件。其中一些文件(我估计2%)实际上是重复的,我需要仅保留每个重复对(或三元组)的一个副本。

你能建议我一种有效的方法吗?我正在使用Unix系统。


重复可以基于以下内容:
  1. 内容
  2. 文件名
您想如何处理?
- coder
基于文件名会太容易了。 - Federico Giorgi
6个回答

2
你可以尝试使用以下代码段来获取所有重复项,然后再进行删除。
find /path -type f -print0 | xargs -0 sha512sum | awk '($1 in seen){print "duplicate: "$2" and "seen[$1] }(!($1 in  seen)){seen[$1]=$2}' 

2
我会编写一个脚本来创建每个文件的哈希值。您可以将哈希值存储在集合中,遍历文件,并在文件的哈希值已经存在于集合中时删除该文件。例如,这在Python中是非常容易实现的。
对于30,000个文件,每个哈希表条目为64字节,您只需要大约200兆字节的空间。

什么是兆字节?一种理想化的字节吗?而且你的解决方案只在你拥有完美的哈希函数时才有效。 - anon
什么不是兆字节?修正。如果担心误删,可以比较文件内容。另外添加一个哈希值也可能有所帮助。 - Joe
如果你使用现代的、目前未被破解的加密哈希函数,并且你发现了碰撞,那么你的算法会崩溃,但是你获得了一张加密纸,所以这是完全胜利的。不过,在删除其中一个之前,比较两个看起来相同的文件是值得的。 - Pascal Cuoq
适当的加密哈希函数并不完美,这可以通过简单的计数论证明,但是你可以将它们视为实际上是完美的。 - Pascal Cuoq
@Pascal 当然可能会发生碰撞。考虑到一个文件可以被视为一个非常大的单一二进制数,比哈希值要大得多。由于哈希值丢失了信息,因此碰撞是不可避免的。 - anon

2

查找可能重复的文件:

find DIR -type f -exec sha1sum "{}" \; | sort | uniq -d -w40

现在,您可以使用cmp来检查文件是否真正相同。

-w 是 GNU uniq 的一个特性;-d 只会找到连续的重复项,所以你需要先进行排序。 - user3850
不要使用-w(就像第一条评论所说的那样,这只在GNU中可用),您可以将sort的输出导入到cut -d \ -f 1,然后将其导入到uniq -d。这更具可移植性。它适用于BSD、OS X和其他系统。 - monokrome
@monokrome:错误...不是这样的。那样只会给你校验和而没有文件名字。如果你没有GNU uniq,你就得使用awk和它的关联数组来模拟uniq - Aaron Digulla

1

有一个现成的工具可用:fdupes

从一个被删除的旧答案中恢复解决方案。


1
编写一个脚本,首先比较文件大小,然后比较MD5校验和(当然要进行缓存),如果你非常担心数据丢失,就勇敢地逐字节比较重复的候选项。如果你对文件的生成方式等没有额外的了解,那么效率上也无法做得更好。

这是一个从不同来源进行高吞吐量下载的过程,因此我得到了一些冗余数据。 我将尝试使用md5sum,以便为它们所有生成哈希码。如果成功了,我会告诉你 :-) - Federico Giorgi

0

将所有文件名保存在一个数组中。然后遍历该数组。在每次迭代中,使用命令md5sum将文件内容与其他文件的内容进行比较。如果MD5相同,则删除该文件。

例如,如果文件b是文件a的副本,则两个文件的md5sum将相同。


你可能要考虑特定方法的算法复杂度。 - user3850

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接