Files

11 KiB
Raw Permalink Blame History

Сортировка фотографий

Утилита приводит новые фотографии к единой структуре архива, находит дубли и создаёт план, который сначала можно проверить вручную. Файлы не перемещаются во время анализа. Перенос начинается только после отдельного подтверждения.

Состав проекта

  • Сортировка фото.command — запуск двойным щелчком в macOS.
  • photo_sort.py — рабочая программа.
  • test_photo_sort.py — автоматические проверки алгоритма.
  • vendor/exiftool/ — локальная копия ExifTool для чтения метаданных. Это сторонний компонент, поэтому его исходные тексты и лицензия сохранены на исходном языке.
  • photo-sort-report-20260914/, photo_sort_20260914.py и photo-sort-summary-20260914.md — архив первой, уже завершённой обработки. Старый скрипт повторно не запускайте.

Быстрый запуск на Mac

  1. Откройте папку проекта и дважды щёлкните Сортировка фото.command.

  2. В меню выберите 1 — анализ папки.

  3. Введите исходную папку с новой партией, обычно:

    /Users/fofanovdmitry/Documents/Pictures/FOTO/BACKUP
    
  4. Введите папку архива:

    /Users/fofanovdmitry/Documents/Pictures/FOTO
    
  5. Оставьте дату пустой, чтобы программа читала дату из фотографии. Введите дату только если она достоверно известна для всех выбранных файлов.

  6. Для поиска версий одной фотографии в разном сжатии или разрешении ответьте д на вопрос о визуальных дублях.

  7. После анализа программа покажет путь к новой папке отчёта. Сначала выберите 2 для ручной проверки, затем 3 для просмотра окончательного списка и только потом 4 для переноса.

  8. Для фактического переноса введите ПЕРЕНЕСТИ.

В первый раз macOS может спросить разрешение Terminal на доступ к папке «Документы». Его нужно разрешить в «Системные настройки → Конфиденциальность и безопасность → Файлы и папки».

Ручная проверка

Папка отчёта создаётся в ~/.photo-sort/runs/. В режиме проверки:

  • o открывает текущую фотографию;
  • w открывает выбранную основную версию;
  • t назначает дату вручную и переводит читаемое фото в сортировку;
  • d переносит файл в _DEL;
  • r переносит файл в _RAS;
  • s оставляет файл на текущем месте;
  • Enter показывает следующую строку;
  • q сохраняет уже внесённые решения и завершает просмотр.

Также можно открыть review.csv в Numbers. Сохраняйте CSV в UTF-8 с запятой как разделителем. Не удаляйте строки и не меняйте id, source, reason, winner; разрешено менять только action и date. Действия в таблице технически записываются как sort, del, ras, skip, keep: первые три означают сортировать, перенести в _DEL, перенести в _RAS; последние два оставляют файл на месте.

Алгоритм работы

  1. Программа берёт все файлы из исходной папки и сравнивает их с фотографиями архива, включая _RAS. Папки _DEL и BACKUP не участвуют в сравнении.
  2. Для каждого изображения программа пытается полностью его декодировать. Поддерживаемые изображения с ошибкой декодирования считаются повреждёнными и направляются в _DEL. Не-фотографии, неподдерживаемые форматы и многостраничные изображения направляются в _RAS.
  3. У читаемой фотографии считываются встроенные поля даты создания контента: EXIF, XMP и IPTC. Время создания или изменения файла в Finder, имя файла и название папки никогда не используются как дата съёмки.
  4. Если во встроенных полях одна согласованная дата, фото получает её. Если даты нет или поля противоречат друг другу, файл направляется в _RAS. Дата не наследуется от другой версии фотографии. Назначенная вручную дата сохраняется только для того же файла в постоянном каталоге.
  5. Поиск дублей проходит в несколько уровней: точный SHA-256 файла, одинаковые декодированные пиксели, а при включённой опции — строгая визуальная проверка миниатюр. Визуальные совпадения следует просматривать вручную.
  6. В каждой группе дублей выбирается один лучший вариант: сначала большее разрешение в пикселях, затем больший размер файла в байтах. При полном равенстве предпочтение получает файл, уже находящийся в архиве.
  7. Худшие варианты переносятся в _DEL. Если лучшая новая версия должна занять имя старой версии, программа сперва надёжно переносит старую в _DEL, затем размещает новую на её месте.
  8. Основные фотографии размещаются по пути ГОД/месяц/ДДММГГГГччммсс.ext, например 2018/октябрь/15102018093000.jpg. При совпадении имени добавляется _dub, затем _dub2 и так далее.
  9. Перед каждым переносом вычисляется SHA-256. Файл копируется без перезаписи, копия проверяется, и лишь затем удаляется исходник. Поэтому для переноса нужен свободный объём хотя бы с размер копируемого файла.

Постоянная база и последующие партии

База ~/.photo-sort/cache.sqlite не удаляется автоматически. В ней хранятся кэш декодирования, пути и хеши известных файлов, группы дублей, ручные даты и история переносов. При следующем анализе BACKUP программа сверяет базу с реальным состоянием архива: вручную перемещённые или удалённые файлы не считаются действующими оригиналами.

Если новая версия лучше старой, старая отправляется в _DEL, а новая занимает её место. Если новая версия хуже, в _DEL попадёт новая. Перемещения записываются в moves.jsonl, а таблица history в постоянной базе сохраняет историю.

Не удаляйте базу без необходимости: при её удалении программе придётся заново проанализировать весь архив. Изменённый файл всё равно проверяется повторно по размеру, inode, времени изменения и SHA-256.

Командная строка

Команды выполняются из папки проекта:

.venv/bin/python photo_sort.py analyze \
  --source "/Users/fofanovdmitry/Documents/Pictures/FOTO/BACKUP" \
  --dest "/Users/fofanovdmitry/Documents/Pictures/FOTO" \
  --visual

.venv/bin/python photo_sort.py review "/путь/к/отчёту" --only unresolved
.venv/bin/python photo_sort.py review "/путь/к/отчёту" --only duplicates
.venv/bin/python photo_sort.py show "/путь/к/отчёту"
.venv/bin/python photo_sort.py apply "/путь/к/отчёту"

Для одного выбранного файла с известной датой:

.venv/bin/python photo_sort.py analyze \
  --source "/путь/FOTO/_RAS" \
  --dest "/путь/FOTO" \
  --select "фото.jpg" \
  --date "2025-05-20 10:10:20"

Другую постоянную базу можно указать параметром --database "/путь/catalog.sqlite".

Восстановление среды и проверка

Если папка .venv отсутствует или Python был обновлён, выполните:

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m unittest -v test_photo_sort.py

ExifTool уже находится в vendor/exiftool. На macOS изображение открывается через open, на Linux — через xdg-open.

Важные ограничения

  • RAW, HEIC и AVIF зависят от доступных декодеров; нечитаемые форматы останутся в _RAS.
  • Изображения больше 100 мегапикселей требуют ручной проверки. Лимит меняется параметром --max-megapixels.
  • После изменения файла или review.csv создайте новый анализ, если план больше не соответствует файлам.
  • Старые планы версии с наследованием даты блокируются. Старые отчёты сохранены, но для новых действий создавайте новый анализ.