2026 年 7 月 2 日 · 3 min read
一个小脚本:把手机相册按日期整理进 NAS
胶片扫描件和手机照片混在一起太乱,写了个脚本按 EXIF 拍摄时间分目录,再同步到 NAS。
Pythonrsyncexiftool
照片越来越多,手机、相机、胶片扫描件全混在一个文件夹里。我要的只是一个简单的规则:按拍摄日期分目录,不重复,不丢。
读 EXIF
文件修改时间不可信(导出、拷贝都会改),要读 EXIF 里的 DateTimeOriginal。用 exiftool 最省事:
import json, subprocess
from pathlib import Path
from datetime import datetime
def taken_at(path: Path) -> datetime | None:
out = subprocess.run(
["exiftool", "-json", "-DateTimeOriginal", "-CreateDate", str(path)],
capture_output=True, text=True,
).stdout
meta = json.loads(out)[0]
raw = meta.get("DateTimeOriginal") or meta.get("CreateDate")
if not raw:
return None
return datetime.strptime(raw[:19], "%Y:%m:%d %H:%M:%S")
胶片扫描件没有 EXIF,就退回到文件名里的日期,再不行就归到 undated/。
分目录 + 去重
目录结构:YYYY/YYYY-MM-DD/。用内容哈希去重,同一张照片再导入一次也不会多一份:
import hashlib, shutil
def sha1(path: Path) -> str:
h = hashlib.sha1()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(1 << 20), b""):
h.update(chunk)
return h.hexdigest()[:12]
def place(src: Path, root: Path):
dt = taken_at(src)
folder = root / (f"{dt:%Y}/{dt:%Y-%m-%d}" if dt else "undated")
folder.mkdir(parents=True, exist_ok=True)
dst = folder / f"{sha1(src)}{src.suffix.lower()}"
if not dst.exists():
shutil.copy2(src, dst)
同步到 NAS
整理完的目录用 rsync 推过去,只传新增:
rsync -av --ignore-existing ~/Pictures/sorted/ nas:/volume1/photos/
一点心得
- 先整理再同步,不要在 NAS 上直接改;
- 哈希用前 12 位就够了,文件名短一点好看;
- 胶片扫描件我会手动在文件名里写上冲扫日期,脚本认得出来。