#!/usr/bin/env python3 """把 static/annotations 根目录下的图片按创建时间(天)归入 YYYY-MM-DD 子目录。 用法: python3 scripts/organize_annotations_by_day.py # 实际移动 python3 scripts/organize_annotations_by_day.py --dry-run # 只预览 python3 scripts/organize_annotations_by_day.py --dir /path # 指定目录 """ from __future__ import annotations import argparse import os import shutil import sys from collections import Counter from datetime import datetime from pathlib import Path IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"} def file_day(path: Path) -> str: """取文件创建日(优先 birth time,否则 mtime),本地时区 YYYY-MM-DD。""" st = path.stat() ts = getattr(st, "st_birthtime", None) or st.st_mtime return datetime.fromtimestamp(ts).strftime("%Y-%m-%d") def main() -> int: repo = Path(__file__).resolve().parent.parent parser = argparse.ArgumentParser(description="按天整理 annotations 图片") parser.add_argument( "--dir", type=Path, default=repo / "static" / "annotations", help="annotations 目录(默认 static/annotations)", ) parser.add_argument( "--dry-run", action="store_true", help="只打印将要执行的操作,不实际移动", ) args = parser.parse_args() root: Path = args.dir.resolve() if not root.is_dir(): print(f"目录不存在: {root}", file=sys.stderr) return 1 files = [ p for p in root.iterdir() if p.is_file() and p.suffix.lower() in IMAGE_EXTS ] if not files: print(f"根目录没有待整理图片: {root}") return 0 by_day: Counter[str] = Counter() moved = 0 skipped = 0 for src in sorted(files): day = file_day(src) dest_dir = root / day dest = dest_dir / src.name by_day[day] += 1 if dest.exists(): print(f"SKIP 目标已存在: {dest.relative_to(root)}") skipped += 1 continue if args.dry_run: print(f"MOVE {src.name} -> {day}/") else: dest_dir.mkdir(parents=True, exist_ok=True) shutil.move(str(src), str(dest)) moved += 1 print("---") print(f"目录: {root}") print(f"{'预览' if args.dry_run else '完成'}: {moved} 个文件" + (f", 跳过 {skipped}" if skipped else "")) for day in sorted(by_day): print(f" {day}: {by_day[day]}") return 0 if __name__ == "__main__": raise SystemExit(main())