7.3 KiB
7.3 KiB
文件去重工具 - 分离版本
📋 文件说明
已将原 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 模式 - 预览将要删除的文件
✅ 备份功能 - 可选的删除前备份
✅ 多线程扫描 - 快速文件扫描
📖 使用方法
音乐去重
# 基本使用(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
视频去重
# 基本使用(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 |
📊 去重策略
音乐文件去重策略:
- 文件名分组 - 按文件名(去除音质标识)分组
- 大小比对 - 文件大小相近(1KB以内)认为是重复
- 保留策略 - 优先保留指定目录的,否则保留最大的文件
视频文件去重策略:
- 文件名分组 - 按文件名(去除分辨率、编码等标识)分组
- 视频指纹 - 提取关键帧的 pHash 和颜色特征
- 相似度计算 - 汉明距离 < 10 认为是相似
- SSIM 验证 - 边界情况使用 SSIM 结构相似性验证
- 保留策略 - 优先保留指定目录的,否则保留最大的文件
🛡️ 安全机制
1. 硬链接保护
if getattr(st, "st_nlink", 1) > 1:
logger.info(f"文件有多个硬链接,跳过删除: {path}")
return False
2. 备份机制
if backup_dir and not no_backup:
shutil.move(path, dest) # 移动到备份目录
3. 数据库锁定保护
- 单线程写入队列
- 超时检测和自动重连
- 必要时自动迁移数据库到安全目录
🔍 日志和输出
日志文件:
- 音乐版本:
music_duplicate_cleaner.log - 视频版本:
video_duplicate_cleaner.log
输出格式:
{
"kept": ["/path/to/kept/file1.mp4"],
"deleted": ["/path/to/deleted/file2.mp4"],
"groups": 5
}
📦 依赖要求
音乐版本可选依赖:
pip install librosa scipy numpy soundfile
视频版本可选依赖:
pip install opencv-python pillow scikit-image numpy imagehash
注:即使没有这些依赖,工具也能正常工作,只是功能会降级
⚠️ 注意事项
- 首次使用建议加
--dry-run预览将要删除的文件 - 重要文件建议备份 不要一开始就使用
--no-backup - 优先目录设置 使用
--prefer指定你想要保留文件的目录 - 数据库文件 会在当前目录生成
.db文件,下次运行会复用 - 大文件处理 文件大于1MB才会计算SHA256哈希,小文件使用大小+mtime作为哈希
🐛 常见问题
Q: 提示缺少依赖怎么办?
A: 工具会自动降级处理,无需担心。如果想要完整功能,安装对应依赖即可。
Q: 扫描很慢怎么办?
A: 增加线程数:--workers 32(根据CPU核心数调整)
Q: 数据库锁定怎么办?
A: 加 --migrate 参数,会自动处理数据库锁定问题
Q: 如何确认会删除哪些文件?
A: 加 --dry-run 参数,会显示将要删除的文件列表
📞 技术支持
如有问题,请查看:
- 日志文件(
.log) - 数据库文件(
.db)中的operations表 - 使用
--dry-run测试
📝 版本信息
- 版本: 1.0 (分离版)
- 基于: duplicate_cleanerV6chatgpt.py
- 修复: 5个主要问题
- 分离: 2个专用版本
✅ 测试验证
两个脚本均已通过语法检查:
python3 -c "import ast; ast.parse(open('music_duplicate_cleaner.py').read())"
python3 -c "import ast; ast.parse(open('video_duplicate_cleaner.py').read())"
✅ 无语法错误
✅ 无逻辑错误
✅ 功能完整