查找重复文件


90

是否可以在磁盘上找到完全相同但文件名不同的重复文件?


3
请注意,这样做的任何可能的方法将总是有比较每一个文件系统上的每一个其他文件。因此,即使使用快捷方式,这也将花费很长时间
Shadur

4
@Shadur如果可以接受校验和,则可以归结为仅比较散列-在大多数系统上,散列的数量级为10 ^(5 + -1),通常<64字节。当然,您必须至少读取一次数据。:)
peterph

15
@Shadur这是不正确的。您可以通过检查是否匹配st_sizes 来减少时间,消除那些仅包含一个相同的s,然后仅计算匹配st_sizes的md5sums 。
克里斯·

6
@Shadur甚至是一种非常愚蠢的方法,它禁止使用任何排序算法(基于文件内容)在Θ(n log n)比较中(而不是Θ(n²))中执行任何哈希操作都可以做到这一点。
derobert

1
@ChrisDown是的,尺寸匹配将是我想到的快捷方式之一。
Shadur

Answers:


104

fdupes可以做到这一点。来自man fdupes

在给定的路径中搜索重复的文件。通过比较文件大小和MD5签名,然后进行逐字节比较,可以找到此类文件。

在Debian或Ubuntu中,您可以使用进行安装apt-get install fdupes。在Fedora / Red Hat / CentOS中,可以使用进行安装yum install fdupes。在Arch Linux上,您可以使用pacman -S fdupes,在Gentoo上,emerge fdupes

要运行从文件系统根目录开始的检查,这可能会花费大量的时间和内存,请使用fdupes -r /

按照评论中的要求,可以通过执行以下操作获得最大的重复项:

fdupes -r . | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n

如果您的文件名包含换行符,这将中断。


谢谢。如何过滤最大的骗子?如何使尺寸易于阅读?
学生

@student:使用类似的东西(确保fdupes仅输出没有多余信息的文件名,或者剪切或sed以便保留该信息):fdupes ....... | xargs ls -alhd | egrep 'M |G '将文件保留为人类可读格式,并且仅保留大小为兆字节或千兆字节的文件。更改命令以适合实际输出。
Olivier Dulac 2013年

2
@OlivierDulac您永远不要解析ls。通常情况下,这种情况比用例要糟,但是即使在用例中,您也冒着误报的风险。
克里斯·

@student-一旦有了文件名,通过du管道sort将告诉您。
克里斯·

@ChrisDown:的确这是一个坏习惯,并且会带来误报。但是在那种情况下(交互式使用,并且仅用于显示,没有“ rm”或直接依赖它的任何形式的东西)就可以了。我喜欢您链接到的那些页面,顺便说一句(几个月以来一直在阅读它们,并且到处都是许多有用的信息)
Olivier Dulac 2013年

26

另一个好的工具是fslint

fslint是一个工具集,用于查找文件系统的各种问题,包括重复文件和有问题的文件名等。

除了GUI之外,还可以使用各种命令行工具来访问它们,可以在标准安装中将/ usr / share / fslint / fslint目录更改为$ usr或将其添加到$ PATH中。该目录中的每个命令都有一个--help选项,可进一步详细说明其参数。

   findup - find DUPlicate files

在基于debian的系统上,您可以使用以下命令进行安装:

sudo apt-get install fslint

如果您不想或无法安装第三方工具,也可以手动执行此操作。大多数此类程序的工作方式是通过计算文件校验和。具有相同md5sum的文件几乎可以肯定包含完全相同的数据。因此,您可以执行以下操作:

find / -type f -exec md5sum {} \; > md5sums
gawk '{print $1}' md5sums | sort | uniq -d > dupes
while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 

样本输出(此示例中的文件名相同,但不同时也可以使用):

$ while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/if_bonding.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/if_bonding.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/route.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/route.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/drm/Kbuild
 /usr/src/linux-headers-3.2.0-4-common/include/drm/Kbuild
---

这将是很多比已经提到的专用工具慢,但它会奏效。


4
使用查找相同大小的文件的速度要快得多st_size,消除只有一个文件大小的文件,然后仅在具有相同大小的文件之间计算md5sums会更快st_size
克里斯·

@ChrisDown是的,只是想保持简单。您的建议当然会大大加快速度。这就是为什么我在回答结束时对它的运行缓慢表示免责。
terdon

8

简短的回答:是的。

更长的版本:看一下Wikipedia fdupes条目,它提供了很好的现成解决方案列表。当然,你可以写你自己的,它不是那个困难的-像哈希程序diffsha*sumfindsortuniq应该做的工作。您甚至可以将其放在一行上,并且仍然可以理解。


6

如果您认为哈希函数(此处为MD5)在您的域中是无冲突的:

find $target -type f -exec md5sum '{}' + | sort | uniq --all-repeated --check-chars=32 \
 | cut --characters=35-

要将相同的文件名分组?编写一个简单的脚本not_uniq.sh来格式化输出:

#!/bin/bash

last_checksum=0
while read line; do
    checksum=${line:0:32}
    filename=${line:34}
    if [ $checksum == $last_checksum ]; then
        if [ ${last_filename:-0} != '0' ]; then
            echo $last_filename
            unset last_filename
        fi
        echo $filename
    else
        if [ ${last_filename:-0} == '0' ]; then
            echo "======="
        fi
        last_filename=$filename
    fi

    last_checksum=$checksum
done

然后更改find命令以使用您的脚本:

chmod +x not_uniq.sh
find $target -type f -exec md5sum '{}' + | sort | not_uniq.sh

这是基本思想。find如果文件名包含一些字符,则可能应该更改。(例如空间)


6

我想添加一个最近增强的fdupes分支jdupes,它比fdupes 更快,功能更丰富(例如,大小过滤器):

jdupes . -rS -X size-:50m > myjdups.txt

这将在当前目录中递归地找到大于50MB的重复文件,并将结果列表输出到myjdups.txt中。

注意,输出不是按大小排序的,并且由于它似乎不是内置的,因此我在上面改编了@Chris_Down答案以实现此目的:

jdupes -r . -X size-:50m | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n > myjdups_sorted.txt

注意:最新版本的jdupes支持仅具有部分哈希的匹配文件,而不必等待对整个对象进行哈希。很有用。(您必须克隆git存档才能获取它。)这是我现在正在使用的选项:jdupes -r -T -T -exclude = size-:50m --nohidden
Benjamin

2

Wikipedia上有一篇文章(http://en.wikipedia.org/wiki/List_of_duplicate_file_finders),其中包含用于此任务的可用开源软件列表,但现已删除

我将添加fslint的GUI版本非常有趣,允许使用掩码选择要删除的文件。清理重复的照片非常有用。

在Linux上,您可以使用:

- FSLint: http://www.pixelbeat.org/fslint/

- FDupes: https://en.wikipedia.org/wiki/Fdupes

- DupeGuru: https://www.hardcoded.net/dupeguru/

我尚未检查FSLint在许多系统(Windows,Mac和Linux)上的2个最新工作


5
这是更好地在这里不提供实际信息只是一个链接,该链接可能会改变,答案有没有留下什么价值
安森

2
维基百科页面为空。
ihor_dvoretskyi 2015年

是的,它已经被清理了,真可惜……
MordicusEtCubitus

我已经使用这3种工具进行了编辑
MordicusEtCubitus 2015年

0

这是我的看法:

find -type f -size +3M -print0 | while IFS= read -r -d '' i; do
  echo -n '.'
  if grep -q "$i" md5-partial.txt; then echo -e "\n$i  ---- Already counted, skipping."; continue; fi
  MD5=`dd bs=1M count=1 if="$i" status=noxfer | md5sum`
  MD5=`echo $MD5 | cut -d' ' -f1`
  if grep "$MD5" md5-partial.txt; then echo "\n$i  ----   Possible duplicate"; fi
  echo $MD5 $i >> md5-partial.txt
done

不同之处在于,它仅哈希到文件的前1 MB。
这有几个问题/功能:

  • 前1 MB之后可能会有所不同,因此结果可能是要检查的候选对象。我稍后可能会解决。
  • 首先按文件大小检查可以加快速度。
  • 仅获取大于3 MB的文件。

我用它来比较视频片段,所以对我来说足够了。

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.