feat: Unify Driveのコピー処理を実装
This commit is contained in:
+65
-8
@@ -3,7 +3,7 @@ title: UnifyDrive2NAS の現状
|
||||
tags:
|
||||
- homelab
|
||||
- UnifyDrive2NAS
|
||||
status: 方式検討中
|
||||
status: コピーコア実装済み
|
||||
---
|
||||
|
||||
# UnifyDrive2NAS の現状
|
||||
@@ -13,8 +13,9 @@ status: 方式検討中
|
||||
|
||||
## 今の状態
|
||||
|
||||
- **方式検討中。** コード・テストはまだ無い
|
||||
- リポジトリ: 未作成
|
||||
- Python 3.8 の標準ライブラリと同梱した `exifread` 3.5.1 だけで動くコピーコアを実装済み
|
||||
- コピー済み一覧、初期化、ドライラン、二重起動防止、マウント確認を含む
|
||||
- NAS への配置と Dagu の DAG 定義は未実施
|
||||
|
||||
## 目的
|
||||
|
||||
@@ -41,6 +42,8 @@ status: 方式検討中
|
||||
| `YYYYMMDD` の日付 | **EXIF の撮影日時 → 動画のメタデータ(QuickTime の作成日時等)→ ファイルの日時**の順に、取れたものを使う(ユーザー判断、2026-10-10) |
|
||||
| 動画の日時の優先順 | **Apple の作成日時(`moov/meta`、タイムゾーン付き)→ `moov/mvhd` の作成日時(UTC を JST に変換)**(ユーザー判断、2026-10-12) |
|
||||
| 隠しファイル | **先頭が `.` のファイル・フォルダはコピーしない**(`.<元の名前>.z<16 進 32 桁>` の書きかけと推定されるファイルを含む)(ユーザー判断、2026-10-12) |
|
||||
| カメラの管理フォルダ内の動画 | **コピー対象とする**。Sony の動画は `PlugBackup/<回>/.../PRIVATE/M4ROOT/CLIP/*.MP4` にあり(2026-10-12 時点で 9 本・約 5.4 GB)、`mvhd` を JST に変換した時刻が同じフォルダの `*M01.XML` の `CreationDate` と一致することを確認済み(ユーザー判断、2026-10-12) |
|
||||
| コピー済み DB の既定値 | `~/.local/state/unifydrive2nas/copied.sqlite3`。`--database` で変更できる |
|
||||
|
||||
## 要件
|
||||
|
||||
@@ -51,11 +54,41 @@ status: 方式検討中
|
||||
|
||||
### 非機能要件
|
||||
|
||||
- 未定
|
||||
- Python 3.8.15 で動作し、`exifread` 以外は標準ライブラリだけを使う
|
||||
- 1 ファイルの失敗で全体を止めず、終了時に非 0 を返す
|
||||
- コピー元は読み取りだけとし、コピー先は一時ファイルからの rename で確定する
|
||||
- コピー元がマウントポイントでない場合または空の場合は処理を開始しない
|
||||
- `fcntl.flock` により同じ DB を使う処理の二重起動を防ぐ
|
||||
|
||||
## 構成(案)
|
||||
## 構成
|
||||
|
||||
未定。[[#未決事項]] を決めてから書く。
|
||||
| パス | 内容 |
|
||||
|---|---|
|
||||
| `unifydrive2nas.py` | ファイル列挙、日時判定、コピー、SQLite 記録、安全装置を持つ CLI |
|
||||
| `vendor/exifread/` | `exifread` 3.5.1 と BSD-2-Clause ライセンス |
|
||||
| `tests/test_unifydrive2nas.py` | 最小の画像・動画バイト列を生成して実行する標準ライブラリ `unittest` |
|
||||
|
||||
SQLite の `copied_files` は、コピー元からの相対パス・サイズ・更新日時(nanosecond)を複合主キーとする。コピー先、日付の出どころ、処理種別、処理日時も記録する。
|
||||
|
||||
### CLI
|
||||
|
||||
既定値は次のとおり。
|
||||
|
||||
| 引数 | 既定値 |
|
||||
|---|---|
|
||||
| `--source` | `/volume1/homes/kazu634/UnifyDrive` |
|
||||
| `--destination` | `/volume1/homes/kazu634/Photos/PhotoLibrary` |
|
||||
| `--database` | `~/.local/state/unifydrive2nas/copied.sqlite3` |
|
||||
|
||||
> [!warning] 初回運用
|
||||
> 本番開始の前日に `python3 unifydrive2nas.py --init` を 1 回実行する。`--init` は現在の対象を DB に登録するだけで、コピーしない。事前確認には `--dry-run` を付ける。
|
||||
|
||||
通常実行とドライランの例:
|
||||
|
||||
```bash
|
||||
python3 unifydrive2nas.py
|
||||
python3 unifydrive2nas.py --dry-run
|
||||
```
|
||||
|
||||
## 外部とのつながり
|
||||
|
||||
@@ -212,6 +245,10 @@ status: 方式検討中
|
||||
- **先頭が `.` の隠しファイル `.<元の名前>.z<16 進 32 桁>` が 14 件ある**(例: `.IMG_2584.MOV.zb0bad79...`、`.DSC07166.JPG.z6d2802...`)。iPhone からのバックアップの途中のファイルか一時ファイルと推定。**コピー対象から外さないと、書きかけのファイルを取り込むおそれがある**
|
||||
- iPhone・iPad・frankel の全 2,331 件を読むのに約 78 秒(ほぼ iPhone)。日々の実行では新しいファイルだけを読むので、時間は問題にならない見込み
|
||||
|
||||
### コピーコアの実機検証
|
||||
|
||||
[実機] 2026-10-12、NAS の Python 3.8.15 で単体テスト 37 件がすべて成功した。実マウントに対する `--dry-run` は、対象 6,786 件・失敗 0 件、日付の出どころは exif 6,081 件・apple 119 件・mvhd 14 件・mtime 572 件で、所要時間は約 3 分 47 秒だった。DB には `/tmp` の使い捨てパスを指定した。
|
||||
|
||||
### コピー先の現状
|
||||
|
||||
[実機] 2026-10-12 確認。
|
||||
@@ -232,7 +269,8 @@ status: 方式検討中
|
||||
|
||||
## 課題
|
||||
|
||||
- なし([[#未決事項]] を参照)
|
||||
- NAS への配置と Dagu の DAG 定義を行う
|
||||
- マウントが NAS 再起動後に自動復旧するか確認する([[#未決事項]])
|
||||
|
||||
## 経緯
|
||||
|
||||
@@ -240,7 +278,26 @@ status: 方式検討中
|
||||
- 2026-10-10: Unify Drive を DHCP(`192.168.10.37`)から固定 IP `192.168.10.200/24` に変更
|
||||
- 2026-10-10: 踏み台から WebDAV でコピー元のディレクトリ構成を調査
|
||||
- 2026-10-12: Dagu → NAS の SSH 鍵を登録。NAS 上の純 Python で撮影日時が取れることを確認
|
||||
- 2026-10-12: Python のコピーコア、SQLite のコピー済み一覧、安全装置、単体テストを実装
|
||||
- 2026-10-12: Apple 作成日時の読み取りを、version/flags の無い QuickTime 形式と FullBox 形式の両方の `meta` に対応
|
||||
|
||||
## 確かめ方
|
||||
|
||||
未定(実装後に書く)。
|
||||
ローカルの単体テスト:
|
||||
|
||||
```bash
|
||||
python3 -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
CLI と引数の確認:
|
||||
|
||||
```bash
|
||||
python3 unifydrive2nas.py --help
|
||||
```
|
||||
|
||||
NAS では配置先で同じ単体テストを実行した後、実マウントを使うドライランで対象と日付の出どころを確認する。
|
||||
|
||||
```bash
|
||||
python3 -m unittest discover -s tests -v
|
||||
python3 unifydrive2nas.py --dry-run
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user