CLI AI

在 Linux 命令行中查找重复文件

2026-06-13

要在 Linux 命令行下查找重复文件又不装任何工具,给每个文件算 md5,再用 uniq 标出重复的:find d -type f -exec md5sum {} + | sort | uniq -w32 -dD。搜索结果里几乎全是先要你装工具的评测文章——fdupes、rdfind、rmlint。但在别人的服务器上或者一次性容器里,往往根本没法装东西。下面是一条完全用系统自带工具搭出来的流程,外加什么时候真的该装个工具的诚实界线。

1. 按内容查找重复文件,无需安装任何工具

clai
$ clai 找出 d 目录下内容相同的文件→ find d -type f -exec md5sum {} + | sort | uniq -w32 -dD4f784201526479699db75d69c7abad6d  d/a/one.txt4f784201526479699db75d69c7abad6d  d/b/two-copy.txt

uniq -w32 只比较每行的前 32 个字符——正好是 md5 哈希的长度,所以比较的是内容而不是文件名。-d 只保留重复项,-D 会打印每组里的所有行,而不是只打印一行。

2. 先统计,再决定

clai
$ clai 一共有多少组重复文件→ find d -type f -exec md5sum {} + | sort | uniq -w32 -d | wc -l

一组对应一行。如果只有三组,肉眼就能看完;如果有三千组,那就需要带交互模式的工具,而不是一条管道。

3. 不要白白哈希几个 TB 的数据

clai
$ clai 只在大于 10MB 的文件里找重复→ find . -type f -size +10M -exec md5sum {} + | sort | uniq -w32 -dD

md5 要读完整个文件。在一棵很大的目录树上,先按大小筛选能把速度提升一个数量级——而且占空间的往往就是大文件。

4. 更快的做法:先按大小筛选,再哈希

clai
$ clai 先按大小筛选,快速找出重复文件→ find . -type f -printf '%s\n' | sort -n | uniq -d | while read s; do find . -type f -size "${s}c" -exec md5sum {} + ; done | sort | uniq -w32 -dD

大小不同的文件不可能是重复文件。只有大小相同的文件才会被哈希。在有一百万个文件的目录树上,这就是几分钟和几小时的差别。

5. 每组只保留一份

clai
$ clai 告诉我哪些重复文件可以删,每组留一份→ find . -type f -exec md5sum {} + | sort | uniq -w32 -d --all-repeated=separate | awk 'seen[$1]++ {print $2}'

awk 'seen[$1]++' 会跳过每个哈希第一次出现的那一行,打印之后所有的——也就是可以删除的候选列表。这份列表是给你看的,不是直接拿去接 xargs rm 的。看一遍再说。

6. 什么时候真的该装个工具

clai
$ clai 找出重复文件,交互式地问我要不要删→ fdupes -r -d .

如果有成百上千组,需要逐组确认,fdupes -d 会问你要保留哪个。rdfind 可以把重复文件替换成硬链接,什么都不删。上面那条管道是给完全没法装包的场景用的。

坑

  • md5 用来找重复够用,但不能用于安全场景。 md5 碰撞可以故意构造出来,但不会偶然发生。要校验完整性用 sha256,找重复文件 md5 更快,也够用。
  • 硬链接看起来也像重复文件。 同一个文件有两个名字,哈希会一样,但只占一份空间。按 inode 号过滤掉它们:find . -type f -printf '%i %p\n' | sort -u -k1,1。
  • 千万别把列表直接传给 rm。 过滤条件写错一处,两份文件都会被删掉。先把列表存成文件,看一遍,再删。

相关问题

怎么按文件名而不是内容找重复? find . -type f -printf '%f\n' | sort | uniq -d 会显示在不同目录里重复出现的文件名。

这在 macOS 上能用吗? 把 md5sum 换成 md5 -r,输出格式是一样的。find 的 -printf 也得换成 -exec stat -f。

几十万个文件时哪种方法最快? 第 4 节里的做法,或者用 rdfind——它会在读盘之前先按 inode 排序。

另请参阅

CliAI 不会替你算哈希,但能让你不用每次都重新想 uniq -w32 这个参数该怎么写。一行命令安装。