Python按文件MD5查找重复文件教程
用Python计算文件MD5哈希值,批量扫描目录找出内容完全相同的重复文件,导出重复清单到Excel,释放磁盘空间。
场景痛点
电脑里存了好几年的文件,同一个合同可能下载了三遍、同一个照片备份了两个文件夹,磁盘越用越满但不知道哪些是重复的。手动对比文件名不靠谱(重命名过),靠大小判断也不准(不同文件可能大小一样)。用MD5哈希:内容完全相同的文件MD5值一定相同,先按大小分组筛掉不可能重复的,再对候选文件算MD5,几秒找出所有重复文件。
用到的库
pip install openpyxl
核心用标准库 os、pathlib、hashlib,导出清单用 openpyxl。
完整代码
import os
import hashlib
from pathlib import Path
from collections import defaultdict
from openpyxl import Workbook
def file_md5(file_path: Path, chunk_size: int = 1024 * 1024) -> str:
"""分块读取文件计算MD5,避免大文件占满内存。"""
md5 = hashlib.md5()
with open(file_path, "rb") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
md5.update(chunk)
return md5.hexdigest()
def find_duplicates(root_dir: str):
"""
两阶段查重:
1. 先按文件大小分组,大小不同的文件内容一定不同
2. 只对大小相同的候选文件算MD5
"""
root = Path(root_dir)
size_map = defaultdict(list)
# 第一阶段:按大小分组
for dirpath, _, filenames in os.walk(root):
for name in filenames:
p = Path(dirpath) / name
try:
size = p.stat().st_size
except OSError:
continue
size_map[size].append(p)
# 第二阶段:对大小相同的文件算MD5
dup_groups = []
for size, files in size_map.items():
if len(files) < 2:
continue # 大小唯一,不可能重复
md5_map = defaultdict(list)
for f in files:
md5 = file_md5(f)
md5_map[md5].append(str(f))
for md5, paths in md5_map.items():
if len(paths) >= 2:
dup_groups.append({
"md5": md5,
"size": size,
"files": paths,
})
return dup_groups
def export_to_excel(groups: list, out_path: str):
wb = Workbook()
ws = wb.active
ws.title = "重复文件"
ws.append(["组号", "MD5", "大小(MB)", "文件路径"])
row = 1
for g in groups:
row += 1
for i, path in enumerate(g["files"]):
ws.append([row if i == 0 else "", g["md5"],
round(g["size"] / 1024 / 1024, 2), path])
ws.column_dimensions['A'].width = 8
ws.column_dimensions['B'].width = 36
ws.column_dimensions['C'].width = 12
ws.column_dimensions['D'].width = 90
wb.save(out_path)
if __name__ == "__main__":
ROOT = r"D:\工作资料"
groups = find_duplicates(ROOT)
total_dup_files = sum(len(g["files"]) for g in groups)
total_waste = sum(g["size"] * (len(g["files"]) - 1) for g in groups)
print(f"发现 {len(groups)} 组重复,共 {total_dup_files} 个文件")
print(f"可释放空间约 {total_waste / 1024 / 1024 / 1024:.2f} GB\n")
for g in groups:
print(f"MD5: {g['md5']} 大小: {g['size']/1024/1024:.1f}MB")
for p in g["files"]:
print(f" - {p}")
print()
export_to_excel(groups, r"D:\工作资料\重复文件清单.xlsx")
print("清单已导出:D:\\工作资料\\重复文件清单.xlsx")
代码讲解
两阶段查重是性能关键:第一阶段按文件大小分组,大小不同的文件内容必然不同,直接跳过。第二阶段只对大小相同的候选文件算MD5,几万个文件里真正需要算哈希的可能只有几百个。file_md5 用1MB分块读取,几个GB的视频文件也不会把内存撑爆。hashlib.md5 更新完调用 hexdigest() 拿到32位十六进制字符串作为指纹。结果按MD5分组,每组里所有文件内容完全一致,保留一份删其他即可。
运行结果
控制台打印每组重复文件的MD5、大小和所有路径,最后统计总重复文件数和可释放空间。同时生成 重复文件清单.xlsx,四列:组号、MD5、大小MB、文件路径。打开后按组号分组看,每组保留一个,其余手动删。
注意事项
- MD5理论上存在哈希碰撞概率,但办公场景下完全够用,不用担心误判。
- 查重只报告不自动删除,确认每组保留哪个后再手动处理,安全第一。
- 大文件(视频、备份包)算MD5比较耗时,第一次跑耐心等,结果可以存下来以后增量比对。
- 软链接、快捷方式不要纳入查重,否则会把同一个源文件当成重复。

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