查找重复文件

stu*_*ent 103 files duplicate-files

是否可以在我的磁盘上找到重复文件,这些文件有点相同但具有不同的文件名?

Chr*_*own 114

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
Run Code Online (Sandbox Code Playgroud)

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

  • @OlivierDulac 你永远不应该[解析 ls](http://mywiki.wooledge.org/ParsingLs)。通常它比您的用例更糟糕,但即使在您的用例中,您也有误报的风险。 (2认同)

ter*_*don 30

另一个好工具是fslint

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

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

   findup - find DUPlicate files
Run Code Online (Sandbox Code Playgroud)

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

sudo apt-get install fslint
Run Code Online (Sandbox Code Playgroud)

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

find / -type f -exec md5sum {} \; > md5sums
awk '{print $1}' md5sums | sort | uniq -d > dupes
while read -r d; do echo "---"; grep -- "$d" md5sums | cut -d ' ' -f 2-; done < dupes 
Run Code Online (Sandbox Code Playgroud)

示例输出(本例中的文件名相同,但在不同时也能工作):

$ while read -r 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
---
Run Code Online (Sandbox Code Playgroud)

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

  • 使用`st_size`查找与另一个文件大小相同的任何文件会快得多,消除任何只有这个大小的文件,然后仅在具有相同`st_size`的文件之间计算md5sums。 (4认同)

pet*_*rph 9

简短的回答:是的。

更长的版本:看看维基百科的fdupes 条目,它提供了相当不错的现成解决方案列表。当然,你可以写你自己的,这不是很难-哈希程序,如diffsha*sumfindsortuniq应该做的工作。你甚至可以把它放在一行上,它仍然是可以理解的。


rei*_*ith 8

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

find $target -type f -exec md5sum '{}' + | sort | uniq --all-repeated --check-chars=32 \
 | cut --characters=35-
Run Code Online (Sandbox Code Playgroud)

想要将相同的文件名分组?编写一个简单的脚本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
Run Code Online (Sandbox Code Playgroud)

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

chmod +x not_uniq.sh
find $target -type f -exec md5sum '{}' + | sort | not_uniq.sh
Run Code Online (Sandbox Code Playgroud)

这是基本思路。find如果您的文件名包含某些字符,您可能应该更改。(例如空格)


Seb*_*ler 7

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

jdupes . -rS -X size-:50m > myjdups.txt
Run Code Online (Sandbox Code Playgroud)

这将递归地查找当前目录中大于 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
Run Code Online (Sandbox Code Playgroud)

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