# photo-organizer v4.0 安装与使用指南

> 📦 让 AI 帮你整理照片：去重（8 种模式）、归档、批量处理
> 🌐 跨平台：macOS / Windows / Linux
> ✅ 实战验证：30GB+ 释放，0 数据丢失

---

## 一、它能做什么（一句话说）

把散落在外置硬盘或本地文件夹里的照片视频，整理成 `YYYYMM/YYYYMMDD/` 的整齐结构，同时去重（小到表情包、大到 HEIC+JPG 双副本）、归档 Office 文档、归档小文件，错位归位（KODAK 相机 mtime=2003 那个经典坑），整套跑完不丢数据。

---

## 二、6 大任务模式

| 模式 | 用途 | 例子 |
|------|------|------|
| `organize` | 按日期归档到 YYYYMMDD 子目录 | 散落照片 → `201810/20181015/` |
| `dedup` | 字节级去重（8 种模式） | jhead _dup、跨日期、HEIC 双副本 |
| `merge` | 跨目录合并 | `200707 + 200801 → 200301` |
| `realign` | 错位归位（KODAK bug 修复） | mtime=2003-01 → 验证 EXIF 后归位 |
| `archive_office` | Office 文档归档 | 删 `.ipa/.exe`，归档 `.doc/.zip` |
| `archive_little` | 小文件归档 | `< 100KB` 表情包统一归档 |

### dedup 模式的 8 种重复识别（v4.0 新增模式 8）

| # | 模式 | 特征 | 处理 |
|---|------|------|------|
| 1 | `jhead_dup` | `IMG_xxxx_dup.JPG` | 绝对安全删 |
| 2 | `cross_date` | 同文件在相邻日期子目录 | 保留 1 份 |
| 3 | `cross_day_img` | 相同 IMG 编号但不同日期 | 防御性保留 |
| 4 | `emoji_hash` | 32 位 hex 命名（表情包） | 保留 1 份 |
| 5 | `burst` | 连拍 `IMG_xxxx + IMG_xxxx_1` | 保留 1 份 |
| 6 | `exif_zero` | EXIF=0000（KODAK 电池没电） | 解析文件名归位 |
| 7 | `kodak_bug` | `mtime=2003-01-XX`（KODAK bug） | **必须验证 EXIF** |
| 8 | `heic_dup` ⭐ | HEIC + JPG 双副本 | **保留 HEIC 删 JPG** |

**模式 8（HEIC 双副本）** 是 v4.0 重点新增。iPhone 拍照会同时保存 HEIC（清晰）+ JPG（兼容副本），可删除 JPG 保留 HEIC 释放约 50%~75% 空间。

---

## 三、安装步骤（5 步，单台机器）

### Step 1: 解压技能包

把 `photo-organizer_v4.0.0.zip` 解压到：

**macOS / Linux**：
```bash
mkdir -p ~/Skills
cd ~/Skills
unzip /path/to/photo-organizer_v4.0.0.zip
# 产出 ~/Skills/photo-organizer/{SKILL.md, INSTALL.md, LONG_TASK.md, scripts/}
```

**Windows**：
1. 右键 `photo-organizer_v4.0.0.zip` → "全部解压"
2. 目标路径：`C:\Users\<你的名字>\Skills\photo-organizer\`

### Step 2: 安装 Python 依赖

```bash
pip install pillow
# 可选（如需查 .rar 压缩包内容）：pip install rarfile
```

`pillow` 是必需的 —— 用于读取 EXIF DateTimeOriginal。

### Step 3: 验证安装

```bash
cd ~/Skills/photo-organizer
python3 -c "from scripts.scan_dedup import scan_dedup; print('OK')"
# 应该打印 OK（即使没有真实文件也能 import）
```

### Step 4:（可选）配置跳过规则

创建 `~/.qclaw/workspace/memory/photo_organizer_config.json`（macOS/Linux）或 `%USERPROFILE%\.qclaw\workspace\memory\photo_organizer_config.json`（Windows）：

```json
{
  "skip_dirs": ["勿动", "private", "FWP"],
  "skip_exts": [".tmp", ".crdownload", ".part"]
}
```

跳过目录名包含 `skip_dirs` 任一项的所有目录；跳过扩展名包含 `skip_exts` 任一项的所有文件。

如果不写这个文件，使用默认值（跳过 `._`、`Thumbs.db`、隐藏文件）。

### Step 5: 在 AI 助手处加载技能

不同 AI 助手的加载方式不同，下表是常见做法：

| AI 助手 | 加载方式 |
|---------|---------|
| **QClaw** | 在 webchat 说"整理照片"会自动加载；也可手动 `skillhub_install photo-organizer` |
| **Claude Code** | 把 `SKILL.md` 复制到 `~/.claude/skills/photo-organizer/SKILL.md` |
| **Cursor** | 把 `SKILL.md` 复制到 `.cursor/rules/photo-organizer.mdc` |
| **Cline / Continue** | 把 `SKILL.md` 复制到对应 skills 目录 |
| **自定义 Agent** | 读 `SKILL.md` 当作 system prompt |

---

## 四、第一次使用（5 分钟上手）

### 用法 A（最简单，跟 AI 说中文）

打开 AI 助手（推荐 webchat），说：

```
帮我整理照片
源盘：/Volumes/你的U盘/201810散落照片/
目标盘：/Volumes/你的U盘/
模式：dedup
```

AI 会自动：
1. 加载 `photo-organizer` 技能
2. 扫描源盘
3. 识别重复（8 种模式）
4. 生成 dry run 报告
5. 等你说"确认执行"
6. 执行 + 输出总结

### 用法 B（详细控制）

```
帮我整理照片，参数如下：
- 源盘：/Volumes/你的U盘/散落/
- 目标盘：/Volumes/你的U盘/
- 模式：organize
- threshold：50（月份目录 > 50 文件才建 YYYYMMDD 子目录）
- dry_run：true（先只出报告不执行）
```

AI 会按参数精细执行。

### 用法 C（命令行 / 脚本）

```python
import sys
sys.path.insert(0, '/Users/你/Skills/photo-organizer')

from scripts.scan_dedup import scan_dedup
from scripts.archive_rules import archive_office_files

# 1. 去重扫描
result = scan_dedup('/Volumes/你的U盘/201810/')
print(f'重复组：{result["stats"]["dupe_groups"]}')

# 2. 归档 Office 文档
office_files = [...]
archived = archive_office_files(office_files, '/Volumes/你的U盘/')
print(f'归档：{len(archived["archived"])} 个')
```

---

## 五、常见任务模板（复制粘贴即可）

### 模板 1：整理散落照片到 YYYYMMDD 子目录
```
整理 /Volumes/My_ExFAT/201810/ 下所有照片/视频，按 EXIF 日期归档到
/Volumes/My_ExFAT/201810/YYYYMM/YYYYMMDD/。
模式：organize
threshold：100（月份 > 100 文件才建日目录）
dry_run：true
```

### 模板 2：清理重复照片（jhead _dup 优先）
```
清理 /Volumes/My_ExFAT/201810/ 下的重复照片。
模式：dedup
重点：jhead _dup（100% 安全的副本）、HEIC + JPG 双副本（同图不同格式）
dry_run：true
```

### 模板 3：跨日期子目录去重
```
扫描 /Volumes/My_ExFAT/201810/ 下跨日期子目录副本
（同一文件出现在 20181001 和 20181002 等），保留一份删除其余。
模式：dedup
pattern_filter：cross_date
```

### 模板 4：错位归位（KODAK bug）
```
扫描 /Volumes/My_ExFAT/200709/ 下所有 mtime=2003-01-XX 的文件，验证 EXIF 后：
- EXIF=2003 → 归到 /Volumes/My_ExFAT/200301/
- EXIF≠2003 → 保留原位
- 无 EXIF → 用 mtime 归到 200301/
模式：realign
```

### 模板 5：Office 文档归档
```
扫描 /Volumes/My_ExFAT/201810/ 下所有非媒体文件：
- .ipa/.exe/.dll/.vsd/.app/.dmg → 删除
- .rar/.zip/.doc/.pdf/.ppt → 归档到 /Volumes/My_ExFAT/Office_doc/YYYYMM/
模式：archive_office
```

### 模板 6：小文件归档（表情包/缩略图）
```
扫描所有 .jpg/.png/.mov/.mp4 且 < 100KB 的文件，归档到 /Volumes/My_ExFAT/LittleFiles/。
模式：archive_little
min_size_kb：100
```

### 模板 7：长任务（超过 30 分钟）
```
跑任务 B2：2018Q3Q4（6 个月份）。
自动按月拆分，每月独立进度守护。
进度文件：~/.qclaw/workspace/memory/B2_progress.json
```

---

## 六、七大铁律（任何 AI 执行此技能都必须遵守）

| # | 铁律 | 核心 |
|---|------|------|
| 1 | 删除三原则 | 指令明确 + 展示样本 + 不确定就问 |
| 2 | 批量必须 dry run | 先看样本，再确认，最后执行 |
| 3 | 删除前保存清单 | 完整路径 + 大小 + 删除依据 |
| 4 | EXIF/mtime 三层 | EXIF 优先 / mtime fallback / 文件名前缀补充 |
| 5 | KODAK bug 防御 | mtime=2003-01 不一定是 2003 年，必须看 EXIF |
| 6 | 长任务必须守护 | 进度文件持久化 + heartbeat + 拆分 |
| 7 | 不说做不到的话 | 不承诺钱 / 不承诺 100% 恢复 |

### 风险分级

| 等级 | 触发条件 | 用户确认要求 |
|------|---------|------------|
| 🟢 极低 | jhead_dup / 文件 < 1KB | 仅一次"确认执行" |
| 🟡 低 | cross_date / emoji_hash / burst / heic_dup | 展示样本 + 一次确认 |
| 🟠 中 | cross_day_img / exif_zero | 两次确认（含 dry run 报告） |
| 🔴 高 | kodak_bug / 大批量 > 1000 文件 / 涉及系统目录 | **三次确认 + 完整清单 + 必须备份** |

---

## 七、典型目录结构

```
整理后：
/Volumes/My_ExFAT/201810/
├── 20181001/
│   ├── IMG_8969.JPG
│   ├── IMG_8970.HEIC        ← 同图 HEIC 版（v4.0 模式 8 优先保留）
│   └── ...
├── 20181002/
└── ...

归档后：
/Volumes/My_ExFAT/
├── Office_doc/202112/        ← 归档的 Office 文档
├── LittleFiles/              ← 归档的小文件
├── 201810/ 201811/ ...        ← 整理后的照片
└── ...

进度文件（v4.0 关键）：
~/.qclaw/workspace/memory/B2-201810_progress.json
```

---

## 八、常见问题排查

| 问题 | 原因 | 解决 |
|------|------|------|
| AI 报错"2066" | 长任务超平台 timeout | 拆分 + 进度守护（铁律 #6） |
| HEIC 删了变模糊 | 删错了，留了 JPG | 模式 8 默认保留 HEIC |
| KODAK 2003 不见了 | 模式 7 没触发 | 用 realign 模式重新归位 |
| 长任务突然停 | 平台 SIGTERM | progress.json 守护 + watchdog |
| progress.json 找不到 | 用了 v3.0 的 `/tmp/tasks/` | v4.0 改用 `~/.qclaw/workspace/memory/` |
| `ModuleNotFoundError: No module named 'PIL'` | pillow 没装 | `pip install pillow` |
| 路径扫描超时 | ExFAT `os.walk` 卡死 | 用 `os.scandir`（脚本已内置） |
| 中文文件名 move 失败 | ExFAT 不支持某些 utf8 字符 | 用 `subprocess.run(['mv', ...])`（脚本已内置） |
| AI 直接删了文件，没问用户 | 没遵守铁律 #1 | 立刻恢复 + 报告 + 重启对话强调铁律 |

---

## 九、升级路径

### 从 v3.0 升级到 v4.0

1. 备份 v3.0：`mv ~/Skills/photo-organizer ~/Skills/photo-organizer.v3.bak`
2. 解压 v4.0 到 `~/Skills/photo-organizer`
3. 配置迁移：`~/.qclaw/workspace/memory/photo_organizer_config.json`（如果有）直接复用
4. 检查进度文件：v3.0 在 `/tmp/tasks/`（已被系统清空），v4.0 在 `~/.qclaw/workspace/memory/`
5. 用模板 2 跑一次扫描，验证 8 种模式都识别正常

### 从 v2.0 及更早升级

直接覆盖安装。v2.0 没有进度守护协议，新版本会创建新格式的 progress.json。

---

## 十、文件清单

```
photo-organizer/
├── SKILL.md           ← 技能契约（必读）
├── INSTALL.md         ← 本文件
├── LONG_TASK.md       ← 长任务守护协议（v4.0 关键）
├── README.md          ← 简短介绍
└── scripts/
    ├── __init__.py
    ├── utils.py       ← 工具函数（文件名规范化、扫描、EXIF、复制）
    ├── scanner.py     ← 旧扫描器（兼容 v2.0 调用）
    ├── dedup_patterns.py  ← 8 种重复模式识别
    ├── scan_dedup.py  ← MD5 字节级去重扫描器
    ├── archive_rules.py   ← Office/LittleFiles 归档规则
    ├── task_guard.py  ← 进度守护（v3.0 兼容 / v4.0 升级版）
    └── executor.py    ← 执行器（移动/复制/删除）
```

---

## 十一、版本历史

| 版本 | 日期 | 改动 |
|------|------|------|
| **v4.0** | 2026-07-16 | 长任务守护 v2 / HEIC 双副本 / 铁律机读化 / 通用化 / 风险分级 / 独立 LONG_TASK.md |
| v3.0 | 2026-06-19 | 7 种模式 + Office/LittleFiles 归档 + 2066/KODAK 防御 |
| v2.0 | 2026-05-22 | 跨平台 + OpenAI-compat API |
| v1.0 | 2026-05-15 | 初版 |

---

**准备好了？把你的源盘路径告诉 AI，开始整理！** 📸