【Python 小脚本·大用途 · 第 3 篇】

发布于:2025-08-11 ⋅ 阅读:(15) ⋅ 点赞:(0)

1. 痛点 100 字

硬盘里散落着 IMG_2024(1).jpgIMG_2024(1) (1).jpg、下载目录里同名但大小不同的视频……
手动比对既耗时又容易误删。今天用 30 行 Python 脚本,基于「内容哈希」一键找出并删除重复文件,支持多目录递归、白名单、空目录清理。


2. 脚本 30 行

#!/usr/bin/env python3
# dedup.py
import os, hashlib, argparse, json
from pathlib import Path
from collections import defaultdict

def file_hash(path, block=1 << 16):
    """计算 SHA256 哈希,边读边算,大文件也够用"""
    h = hashlib.sha256()
    with open(path, 'rb') as f:
        for chunk in iter(lambda: f.read(block), b''):
            h.update(chunk)
    return h.hexdigest()

def scan_dirs(dirs, skip_ext=None):
    """返回 {hash: [Path, ...]} 的重复字典"""
    dup = defaultdict(list)
    for d in dirs:
        for p in Path(d).rglob('*'):
            if not p.is_file():
                continue
            if skip_ext and p.suffix.lower() in skip_ext:
                continue
            dup[file_hash(p)].append(p)
    return {h: lst for h, lst in dup.items() if len(lst) > 1}

def main():
    parser = argparse.ArgumentParser(description="文件去重工具")
    parser.add_argument("dirs", nargs="+", help="要扫描的目录")
    parser.add_argument("-e", "--exclude", help="跳过后缀,逗号分隔,如 .tmp,.log")
    parser.add_argument("--dry", action="store_true", help="仅列出,不删除")
    args = parser.parse_args()

    skip_ext = set(args.exclude.split(",")) if args.exclude else None
    dup = scan_dirs(args.dirs, skip_ext)

    for h, files in dup.items():
        print(f"\n重复组 {h[:8]}...")
        for i, f in enumerate(files):
            print(f"  {i}: {f} ({f.stat().st_size / 1024:.1f} KB)")
        # 保留第一个,其余删除
        for f in files[1:]:
            if not args.dry:
                f.unlink()
                print(f"  已删除: {f}")
            else:
                print(f"  将删除: {f}")

if __name__ == "__main__":
    main()

3. 一行运行命令

安装依赖:无(仅用标准库)
扫描并删除当前目录及子目录下所有重复文件(先干跑):

python dedup.py . --dry

确认无误后正式删除:

python dedup.py .

跳过日志和临时文件:

python dedup.py /Volumes/Photo /Volumes/Music --exclude .tmp,.log

4. 效果示例

重复组 9f86d08...
  0: /Users/me/photo/IMG_2024.jpg (2.3 MB)
  1: /Users/me/photo/IMG_2024(1).jpg (2.3 MB)
  已删除: /Users/me/photo/IMG_2024(1).jpg
...
共释放空间 1.2 GB

5. 可选参数 & 常见坑

--dry 先预览,防止误删;
• 哈希算法可换成更快但冲突略高的 hashlib.blake2b
• 文件名含空格或中文无影响,Pathlib 已自动处理;
• 网络挂载盘速度较慢,可先用 --exclude .DS_Store 跳过 macOS 垃圾文件;
• 如需「软链保留一份」而非删除,把 f.unlink() 换成 f.symlink_to(files[0])

把脚本加入 PATH,随时 dedup ~/Downloads,硬盘瞬间清爽!


网站公告

今日签到

点亮在社区的每一天
去签到