应分块读取文件并增量计算哈希值,避免一次性加载大文件至内存;须以二进制模式打开文件,推荐使用hashlib.md5()或hashlib.sha256()配合update()方法,每次读取8192字节。

用 hashlib 计算文件哈希值,避免逐字节比对的性能灾难
直接用 open().read() 逐个读取并比较内容,对大文件(比如几个 GB 的视频)会卡死或内存爆掉。正确做法是分块读取、增量计算哈希——hashlib.md5() 或 hashlib.sha256() 支持 update(),每次只读 8192 字节。
关键点:
- 不要用
hashlib.md5(file_content)一次性加载整个文件到内存 - 必须用
with open(path, "rb") as f:二进制模式打开,否则文本模式会破坏哈希一致性 -
sha256比md5更抗碰撞,但速度略慢;日常去重用md5足够 - 小文件(os.path.getsize(path),能快速筛掉 90% 明显不同的文件
用字典按哈希值聚类文件路径,注意键类型和路径编码
哈希对象的 digest() 返回 bytes,不能直接当字典键;要用 hexdigest() 转成 str 才安全。同时 Windows 路径含中文、空格、特殊符号时,os.walk() 返回的路径本身是 Unicode 字符串,无需额外 decode。
常见错误:
立即学习“Python免费学习笔记(深入)”;
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 把
hash_obj.digest()当作字典 key → 报TypeError: unhashable type: 'bytes' - 在 Linux 上用
path.encode("utf-8")再哈希 → 实际上文件内容才是哈希目标,路径编码无关 - 忽略大小写:Windows 下
A.txt和a.txt是不同文件,但用户常认为重复 → 建议统一转小写再比对(仅用于显示归类,不用于删除决策)
安全删除前必须人工确认,os.remove() 不进回收站
Python 的 os.remove() 是永久删除,不可恢复。哪怕你写了“只删副本”的逻辑,也可能因硬链接、符号链接或权限问题误删原文件。
实操建议:
- 先输出所有疑似重复组(按哈希值分组),每组列出完整路径和文件大小,让用户用眼睛扫一遍
- 提供交互式选项:输入序号保留某一个,其余标记为待删;或全部跳过
- 真要删时,优先用
send2trash库(pip install send2trash),调用系统回收站:send2trash.send2trash(path) - 绝对不要在根目录、
/System、C:\Windows等系统路径上自动递归扫描
跨磁盘/挂载点时,os.walk() 无法跳过,需手动限制起点
os.walk(top) 默认会下钻所有子目录,包括挂载的网络盘、移动硬盘、甚至 /proc、/sys(Linux)。不加控制可能卡住、报错 PermissionError,或意外扫描到不该碰的分区。
解决方式:
- 显式传入多个起始路径:
for root in ["/home/user/docs", "/mnt/external/photos"]:,而不是只传"/" - 用
os.stat(root).st_dev判断是否跨设备,遇到不同st_dev就break当前分支(防止跨磁盘递归) - 捕获
OSError和PermissionError,记录警告但不停止主流程 - 跳过常见虚拟/系统目录:检查
root是否以".git"、"__pycache__"、"node_modules"开头,直接continue

















