我的知识记录

Python 查找重复文件并删除:按 MD5 去重实战

用 Python 按文件大小和 MD5 哈希找出重复文件,保留一份删掉其余,释放磁盘空间,附 dry-run 预览和按目录优先保留策略。

场景痛点

照片备份、资料下载、项目迭代,同一张图、同一份 PDF 散在好几个文件夹,重复占空间,手动根本分不出哪份是真重复。用文件大小先粗筛、再用 MD5 哈希精验,内容相同的文件不管叫什么名字都能认出来。保留一份,把其余重复列出来给你确认后删除,腾磁盘空间。

用到的库

纯标准库,无需 pip 安装:

# os、hashlib 为标准库

完整代码

import os
import hashlib

# ========== 配置区 ==========
SCAN_DIR = "./素材库"          # 要扫描重复文件的目录
DRY_RUN = True
KEEP_FIRST = True             # True=保留每一组里第一个,删其余
# ============================


def md5_of_file(path: str, chunk_size: int = 1024 * 1024) -> str:
"""分块读取算 MD5,避免大文件一次性读进内存。"""
h = hashlib.md5()
with open(path, "rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()


def main():
if not os.path.isdir(SCAN_DIR):
print(f"目录不存在:{SCAN_DIR}")
return

# 第一遍:按大小分组,大小不同的文件内容一定不同
size_map = {}
for dirpath, _, filenames in os.walk(SCAN_DIR):
for name in filenames:
p = os.path.join(dirpath, name)
size = os.path.getsize(p)
size_map.setdefault(size, []).append(p)

# 第二遍:只对大小相同的文件算 MD5
hash_map = {}
for size, paths in size_map.items():
if len(paths) < 2:
continue  # 大小唯一,不可能重复,跳过省时间
for p in paths:
try:
h = md5_of_file(p)
except (PermissionError, OSError):
continue
hash_map.setdefault(h, []).append(p)

# 找出有重复的组
dup_groups = {h: ps for h, ps in hash_map.items() if len(ps) > 1}
print(f"发现 {len(dup_groups)} 组重复文件:\n")

freed = 0
to_delete = []
for h, paths in dup_groups.items():
print(f"[重复组] {len(paths)} 个:")
for p in paths:
print(f"    {p}")
# 保留第一个,其余标记删除
for p in paths[1:]:
to_delete.append(p)
freed += os.path.getsize(p)
print()

print(f"将删除 {len(to_delete)} 个文件,释放约 {freed/1024/1024:.1f} MB")
if not DRY_RUN:
for p in to_delete:
os.remove(p)
print("已删除多余副本,每组保留一份。")
else:
print("当前是预览。确认保留策略合理,把 DRY_RUN 改成 False 再跑。")


if __name__ == "__main__":
main()

代码讲解

  • 两遍筛查:第一遍按文件大小分组,大小不同的文件内容必然不同,直接排除;第二遍只对大小相同的文件算 MD5。这样能省掉绝大部分哈希计算,扫整个素材库也快。
  • 分块读 MD5md5_of_file 每次读 1MB 进内存,几个 G 的视频也不会把内存撑爆。
  • MD5 判等:两个文件 MD5 相同,内容几乎可以认为一样(碰撞概率可忽略)。不管文件名叫什么、在哪个目录,内容相同就归为一组。
  • 保留策略:每组保留 paths[0],其余标记删除。paths[0] 是 os.walk 遍历到的第一个文件。想按"路径最短/名字最规范"保留,自己排一下顺序即可。

运行结果

终端打印每一组重复文件的完整路径,告诉你将删几个、释放多少 MB。预览看清楚每组里保留的那份是不是你想留的,把 DRY_RUN 改成 False 正式去重。

注意事项

  • 保留哪份要自己看:脚本默认保留遍历到的第一个。重要资料组里,肉眼确认保留的不是旧版本/坏文件,再跑真删。
  • MD5 不是加密用途:这里只是内容指纹,用来判等足够,别拿它做安全相关的事。
  • 文件名不同但内容相同才是重复:MD5 相同就会被识别。如果你想要的是"同名文件重复",那是另一种逻辑,别混。
  • 软链接:本脚本会把软链接当文件读,可能误删。素材库里软链接多就加 os.path.islink(p) 判断跳过。
  • 删除不可逆:真删前最好先把要删的清单导出来存一份,或者先移到一个 _待删 文件夹观察几天再清空。

Python 查找重复文件并删除:按 MD5 去重实战

标签:

更新时间:2026-09-14 21:18:03

上一篇:Python 查找大文件:定位磁盘空间杀手

下一篇:Python按文件MD5查找重复文件教程