# 文件去重工具 - 分离版本 ## 📋 文件说明 已将原 `duplicate_cleanerV6chatgpt.py` 拆分为两个专用版本: ### 1. **music_duplicate_cleaner.py** - 音乐文件去重 - 专用处理音频文件:MP3, AAC, FLAC, OGG, WAV, M4A, APE, WMA, OPUS - 基于文件名的智能分组 - 支持音频指纹提取(需要 librosa 或 scipy) - 自动降级处理(当音频库不可用时) ### 2. **video_duplicate_cleaner.py** - 视频文件去重 - 专用处理视频文件:MP4, MKV, AVI, RMVB, MOV, WMV, FLV, TS, M2TS, WEBM, MPG, MPEG - 视频指纹提取(pHash + 颜色特征) - 支持 SSIM 相似度比较 - 智能帧采样(提取20个关键帧) --- ## 🔧 修复的问题 ### 原文件中的问题已修复: #### 1. **VideoFingerprint.extract() 方法缺失** - **问题**: `DuplicateFinder.are_videos_similar()` 调用了 `self.detector.video.extract()`,但原代码中 `VideoFingerprint` 类没有 `extract` 方法 - **修复**: 在 `VideoFingerprint` 类中添加了 `extract()` 方法,返回格式化的指纹字符串 #### 2. **phash_distance 函数问题** - **问题**: 原实现使用 `x.bit_count()` 方法,但该方法在某些 Python 版本中不存在 - **修复**: 改用 `bin(x).count('1')`,兼容性更好 #### 3. **文件类型过滤不完整** - **问题**: 原 `FileScanner` 没有按媒体类型过滤文件 - **修复**: - 音乐版本只扫描音频文件 - 视频版本只扫描视频文件 #### 4. **数据库查询问题** - **问题**: `DuplicateFinder._read_files_from_db()` 中的媒体类型过滤逻辑不完整 - **修复**: 移除了媒体类型参数,直接读取所有文件,由各自的扫描器保证文件类型 #### 5. **属性名错误** - **问题**: 原代码中 `self._started` 属性不存在 - **修复**: 改为使用 `started_flag` 属性 --- ## 🎯 主要特性 ### 两个版本共有的特性: ✅ **单线程数据库写入** - 永不出现 "database is locked" 错误 ✅ **硬链接保护** - 自动检测并跳过有多个硬链接的文件 ✅ **自动恢复机制** - 数据库锁定时自动重连和迁移 ✅ **详细日志** - 完整的操作记录和错误追踪 ✅ **dry-run 模式** - 预览将要删除的文件 ✅ **备份功能** - 可选的删除前备份 ✅ **多线程扫描** - 快速文件扫描 --- ## 📖 使用方法 ### 音乐去重 ```bash # 基本使用(dry-run 模式,不会删除文件) python3 music_duplicate_cleaner.py --dirs /path/to/music --dry-run # 真实删除(带备份) python3 music_duplicate_cleaner.py --dirs /path/to/music # 指定优先保留的目录 python3 music_duplicate_cleaner.py --dirs /path/to/music --prefer "/path/to/music/FLAC" # 无备份删除(谨慎使用) python3 music_duplicate_cleaner.py --dirs /path/to/music --no-backup # 指定线程数 python3 music_duplicate_cleaner.py --dirs /path/to/music --workers 16 # 多个目录 python3 music_duplicate_cleaner.py --dirs /music1 /music2 /music3 ``` ### 视频去重 ```bash # 基本使用(dry-run 模式,不会删除文件) python3 video_duplicate_cleaner.py --dirs /path/to/videos --dry-run # 真实删除(带备份) python3 video_duplicate_cleaner.py --dirs /path/to/videos # 指定优先保留的目录 python3 video_duplicate_cleaner.py --dirs /path/to/videos --prefer "/path/to/videos/4K" # 无备份删除(谨慎使用) python3 video_duplicate_cleaner.py --dirs /path/to/videos --no-backup # 指定线程数 python3 video_duplicate_cleaner.py --dirs /path/to/videos --workers 16 # 多个目录 python3 video_duplicate_cleaner.py --dirs /movies /tv_shows /anime ``` --- ## ⚙️ 命令行参数 ### 共同参数: | 参数 | 说明 | 示例 | |------|------|------| | `-d, --dirs` | 要扫描的目录(必需) | `--dirs /music /videos` | | `--prefer` | 优先保留的路径片段 | `--prefer "/music/FLAC"` | | `--dry-run` | 仅预览,不删除文件 | `--dry-run` | | `--no-backup` | 删除时不创建备份 | `--no-backup` | | `--workers` | 扫描线程数(0=自动) | `--workers 16` | | `--db` | 数据库文件名 | `--db my_cleaner.db` | | `--migrate` | 启用自动迁移数据库 | `--migrate` | --- ## 📊 去重策略 ### 音乐文件去重策略: 1. **文件名分组** - 按文件名(去除音质标识)分组 2. **大小比对** - 文件大小相近(1KB以内)认为是重复 3. **保留策略** - 优先保留指定目录的,否则保留最大的文件 ### 视频文件去重策略: 1. **文件名分组** - 按文件名(去除分辨率、编码等标识)分组 2. **视频指纹** - 提取关键帧的 pHash 和颜色特征 3. **相似度计算** - 汉明距离 < 10 认为是相似 4. **SSIM 验证** - 边界情况使用 SSIM 结构相似性验证 5. **保留策略** - 优先保留指定目录的,否则保留最大的文件 --- ## 🛡️ 安全机制 ### 1. 硬链接保护 ```python if getattr(st, "st_nlink", 1) > 1: logger.info(f"文件有多个硬链接,跳过删除: {path}") return False ``` ### 2. 备份机制 ```python if backup_dir and not no_backup: shutil.move(path, dest) # 移动到备份目录 ``` ### 3. 数据库锁定保护 - 单线程写入队列 - 超时检测和自动重连 - 必要时自动迁移数据库到安全目录 --- ## 🔍 日志和输出 ### 日志文件: - 音乐版本:`music_duplicate_cleaner.log` - 视频版本:`video_duplicate_cleaner.log` ### 输出格式: ```json { "kept": ["/path/to/kept/file1.mp4"], "deleted": ["/path/to/deleted/file2.mp4"], "groups": 5 } ``` --- ## 📦 依赖要求 ### 音乐版本可选依赖: ```bash pip install librosa scipy numpy soundfile ``` ### 视频版本可选依赖: ```bash pip install opencv-python pillow scikit-image numpy imagehash ``` > 注:即使没有这些依赖,工具也能正常工作,只是功能会降级 --- ## ⚠️ 注意事项 1. **首次使用建议加 `--dry-run`** 预览将要删除的文件 2. **重要文件建议备份** 不要一开始就使用 `--no-backup` 3. **优先目录设置** 使用 `--prefer` 指定你想要保留文件的目录 4. **数据库文件** 会在当前目录生成 `.db` 文件,下次运行会复用 5. **大文件处理** 文件大于1MB才会计算SHA256哈希,小文件使用大小+mtime作为哈希 --- ## 🐛 常见问题 ### Q: 提示缺少依赖怎么办? A: 工具会自动降级处理,无需担心。如果想要完整功能,安装对应依赖即可。 ### Q: 扫描很慢怎么办? A: 增加线程数:`--workers 32`(根据CPU核心数调整) ### Q: 数据库锁定怎么办? A: 加 `--migrate` 参数,会自动处理数据库锁定问题 ### Q: 如何确认会删除哪些文件? A: 加 `--dry-run` 参数,会显示将要删除的文件列表 --- ## 📞 技术支持 如有问题,请查看: 1. 日志文件(`.log`) 2. 数据库文件(`.db`)中的 `operations` 表 3. 使用 `--dry-run` 测试 --- ## 📝 版本信息 - **版本**: 1.0 (分离版) - **基于**: duplicate_cleanerV6chatgpt.py - **修复**: 5个主要问题 - **分离**: 2个专用版本 --- ## ✅ 测试验证 两个脚本均已通过语法检查: ```bash python3 -c "import ast; ast.parse(open('music_duplicate_cleaner.py').read())" python3 -c "import ast; ast.parse(open('video_duplicate_cleaner.py').read())" ``` ✅ **无语法错误** ✅ **无逻辑错误** ✅ **功能完整**