扫描目录中的图片和视频文件(包含 HEIF/HEIC),当文件缺失拍摄时间元数据时,将文件系统“最后修改时间”写入元数据。
- 递归扫描并跟随目录软链接。
- 支持目录排除(如
#recycle、.thumb、@eaDir)。 - 三阶段流水线:
预扫描 -> 筛选 -> 写回。 - 每个阶段都可输出/复用 JSONL 中间产物,避免重复扫描。
- 筛选/写回阶段按“每条记录”输出处理结果,不再按间隔节流。
- 写回前输出待修改清单,支持
--dry-run。 - 写入前自动备份原文件,失败时自动回滚。
- 修复 Windows 多线程场景下
gbk解码崩溃(统一按字节读取并安全解码)。
脚本入口:fill_missing_exif.py
以下命令等价于执行完整流水线:
python fill_missing_exif.py P:\ --dry-run --backup-dir P:\photo_backup说明:
- 默认子命令是
run,所以老用法仍可用。 - 中间文件自动保存到备份目录下:
<backup_dir>/.missing_exif_state/。 - 再次运行时会优先复用中间文件:
discover_<hash>.jsonlplan_<hash>.jsonl
- 如需强制重跑阶段:
--refresh-discover--refresh-filter
扫描所有符合条件的媒体文件并输出 JSONL:
python fill_missing_exif.py discover P:\ --backup-dir P:\photo_backup \
--exclude-dir "#recycle,.thumb,@eaDir,photo_backup" \
--output P:\photo_backup\.missing_exif_state\discover.jsonl并发检查哪些文件缺失 EXIF/XMP/QuickTime/Keys/IPTC 元数据:
python fill_missing_exif.py filter P:\ --backup-dir P:\photo_backup \
--input P:\photo_backup\.missing_exif_state\discover.jsonl \
--output P:\photo_backup\.missing_exif_state\plan.jsonl \
--scan-workers 32读取计划并执行写回:
python fill_missing_exif.py write P:\ \
--input P:\photo_backup\.missing_exif_state\plan.jsonl \
--dry-run正式写入:
python fill_missing_exif.py write P:\ \
--input P:\photo_backup\.missing_exif_state\plan.jsonl \
-y按 plan 持续重试直到全部成功(适合网络盘偶发权限冲突):
python fill_missing_exif.py write P:\ \
--input P:\photo_backup\.missing_exif_state\plan.jsonl \
-y --retry-until-success --retry-interval-seconds 10可以直接通过标准输入/输出串联三个阶段:
python fill_missing_exif.py discover P:\ --backup-dir P:\photo_backup --output - \
| python fill_missing_exif.py filter P:\ --backup-dir P:\photo_backup --input - --output - \
| python fill_missing_exif.py write P:\ --input - --dry-run说明:日志输出在 stderr,JSONL 数据在 stdout,因此可安全 pipe。
项目提供 Dockerfile,容器内包含 python + exiftool。镜像主要提供运行环境。
docker build -t missing-exif:latest .后续仅修改脚本代码时,不需要重建镜像。挂载项目目录到 /workspace 后,容器会优先执行挂载目录中的 fill_missing_exif.py。
docker run --rm -it \
-e TZ=Asia/Shanghai \
-v /volume1/docker/missing_exif:/workspace:ro \
-v /volume1/PhotoHomes:/data \
-v /volume1/PhotoHomes/photo_backup:/backup \
missing-exif:latest \
/data --dry-run --backup-dir /backup \
--exclude-dir "#recycle,.thumb,@eaDir,photo_backup"后台模式不要加 -it,并使用 -y 跳过交互:
docker run -d --name missing-exif-job \
-e TZ=Asia/Shanghai \
-v /volume1/docker/missing_exif:/workspace:ro \
-v /volume1/PhotoHomes:/data \
-v /volume1/PhotoHomes/photo_backup:/backup \
missing-exif:latest \
/data --backup-dir /backup -y \
--exclude-dir "#recycle,.thumb,@eaDir,photo_backup"查看日志:
docker logs -f missing-exif-jobtarget_dir:要扫描的目录。--backup-dir:备份目录(相对路径会拼接到target_dir下)。--exclude-dir:按目录名排除,支持重复传入和逗号分隔。--scan-workers:筛选阶段并发线程数。--retry-until-success:写回失败后按失败项持续重试,直到全部成功。--retry-interval-seconds:重试间隔秒数,默认 10。--retry-max-rounds:最大重试轮次,0 表示不限制。--dry-run:只预览,不执行写回。-y/--yes:跳过写回确认。--refresh-discover:强制重跑预扫描阶段。--refresh-filter:强制重跑筛选阶段。
本仓库包含可直接安装的 Skill:skills/fill-missing-exif。
Linux/macOS:
python ~/.codex/skills/.system/skill-installer/scripts/install-skill-from-github.py \
--repo jasoft/missing_exif \
--path skills/fill-missing-exifWindows:
python $env:USERPROFILE\.codex\skills\.system\skill-installer\scripts\install-skill-from-github.py `
--repo jasoft/missing_exif `
--path skills/fill-missing-exif安装后重启 Codex 以加载新 Skill。