真正可靠的去重依据是内容哈希,如sha256;需分块计算、跳过元数据干扰、区分容器差异,结合软链接验证与白名单保护,再按时间戳保留一份并人工抽检后删除。

用文件哈希值比对,而不是文件名或大小
文件名相同不代表内容相同,文件大小一致也可能是巧合。真正可靠的去重依据是内容哈希——只要两个文件的 sha256(或 md5)完全一致,就能确认它们是同一份数据。
常见错误是只按 os.path.getsize() 分组,结果把不同图片误判为重复;或者用 filecmp.cmp() 逐对比较,面对几千个文件时性能崩盘。
- 优先选
sha256:抗碰撞更强,md5在极端情况下有风险(虽然对普通媒体文件影响极小) - 大文件别一次性读入内存:
hashlib.sha256()支持分块更新,用with open(..., 'rb') as f:配合for chunk in iter(lambda: f.read(8192), b'') - 跳过已知元数据干扰项:比如某些手机相册会修改
.jpg的 EXIF 时间戳但不改图像内容,此时直接哈希原始字节更稳妥
处理视频文件要留意容器封装差异
同一段视频用不同工具转码后,哪怕画面声音完全一样,sha256 也会不同——因为 MP4/AVI/MKV 容器里的时间戳、编码参数、字节对齐方式可能不同。
如果目标是“内容级去重”,不能直接哈希整个文件。需要先提取关键帧或音轨指纹,但成本高;更现实的做法是:先用哈希快速筛出“确定重复”的文件,再对哈希相同但扩展名不同的候选集做二次判断。
立即学习“Python免费学习笔记(深入)”;
- 扩展名不一致但哈希相同?大概率是手动改名,可安全删除旧名文件
- 扩展名相同但哈希不同?保留全部,不强行合并
- 想进一步判断视频内容相似性,可考虑
ffmpeg提取首帧 +cv2计算感知哈希(cv2.img_hash.pHash()),但速度慢,建议仅用于哈希相同后的细粒度验证
安全删除前必须做软链接验证和白名单保护
脚本删错一个家庭录像就不可逆。不能依赖单次哈希结果直接 os.remove()。
实际操作中,先生成报告,再人工抽检,最后批量执行——这个流程不能跳。
- 把所有哈希相同的文件按组写入 CSV,每行包含路径、大小、修改时间、哈希值
- 对每组保留最老或最新的一份(用
max(file.stat().st_mtime)或min()控制),其余标记为待删 - 加白名单机制:硬编码排除类似
'/backup/'、'/important/'这类路径,或读取.keep文件列表 - 真正删除前,先用
os.symlink()创建指向原文件的软链接到临时目录,确认无误再删原文件——这样即使出错也能快速恢复
小文件多时用 scandir 替代 listdir,并避免递归陷阱
遍历几万张图时,os.walk() 会反复打开父目录,而 os.scandir() 返回 DirEntry 对象,能直接拿到 stat() 和 is_file(),快 2–3 倍。
同时注意符号链接和挂载点:默认递归会钻进 /proc、/sys 或远程 NFS 目录,导致卡死或权限错误。
- 用
entry.is_file(follow_symlinks=False)跳过软链接本身(不解析目标) - 检查
entry.stat().st_dev,与根目录os.stat(base_path).st_dev不同就跳出该子树(防止跨设备遍历) - 限制最大深度:自己写个计数器,超过 5 层就停止向下,避免陷入
node_modules或.git这类深目录
哈希计算本身是 I/O 密集型任务,CPU 并不瓶颈;真正拖慢的是磁盘随机读——所以顺序扫描+合理缓存哈希结果,比多线程反而更稳。


















