11 KiB
Сортировка фотографий
Утилита приводит новые фотографии к единой структуре архива, находит дубли и создаёт план, который сначала можно проверить вручную. Файлы не перемещаются во время анализа. Перенос начинается только после отдельного подтверждения.
Состав проекта
Сортировка фото.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
-
Откройте папку проекта и дважды щёлкните
Сортировка фото.command. -
В меню выберите
1— анализ папки. -
Введите исходную папку с новой партией, обычно:
/Users/fofanovdmitry/Documents/Pictures/FOTO/BACKUP -
Введите папку архива:
/Users/fofanovdmitry/Documents/Pictures/FOTO -
Оставьте дату пустой, чтобы программа читала дату из фотографии. Введите дату только если она достоверно известна для всех выбранных файлов.
-
Для поиска версий одной фотографии в разном сжатии или разрешении ответьте
дна вопрос о визуальных дублях. -
После анализа программа покажет путь к новой папке отчёта. Сначала выберите
2для ручной проверки, затем3для просмотра окончательного списка и только потом4для переноса. -
Для фактического переноса введите
ПЕРЕНЕСТИ.
В первый раз 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; последние два оставляют файл на месте.
Алгоритм работы
- Программа берёт все файлы из исходной папки и сравнивает их с фотографиями архива, включая
_RAS. Папки_DELиBACKUPне участвуют в сравнении. - Для каждого изображения программа пытается полностью его декодировать. Поддерживаемые изображения с ошибкой декодирования считаются повреждёнными и направляются в
_DEL. Не-фотографии, неподдерживаемые форматы и многостраничные изображения направляются в_RAS. - У читаемой фотографии считываются встроенные поля даты создания контента: EXIF, XMP и IPTC. Время создания или изменения файла в Finder, имя файла и название папки никогда не используются как дата съёмки.
- Если во встроенных полях одна согласованная дата, фото получает её. Если даты нет или поля противоречат друг другу, файл направляется в
_RAS. Дата не наследуется от другой версии фотографии. Назначенная вручную дата сохраняется только для того же файла в постоянном каталоге. - Поиск дублей проходит в несколько уровней: точный SHA-256 файла, одинаковые декодированные пиксели, а при включённой опции — строгая визуальная проверка миниатюр. Визуальные совпадения следует просматривать вручную.
- В каждой группе дублей выбирается один лучший вариант: сначала большее разрешение в пикселях, затем больший размер файла в байтах. При полном равенстве предпочтение получает файл, уже находящийся в архиве.
- Худшие варианты переносятся в
_DEL. Если лучшая новая версия должна занять имя старой версии, программа сперва надёжно переносит старую в_DEL, затем размещает новую на её месте. - Основные фотографии размещаются по пути
ГОД/месяц/ДДММГГГГччммсс.ext, например2018/октябрь/15102018093000.jpg. При совпадении имени добавляется_dub, затем_dub2и так далее. - Перед каждым переносом вычисляется 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создайте новый анализ, если план больше не соответствует файлам. - Старые планы версии с наследованием даты блокируются. Старые отчёты сохранены, но для новых действий создавайте новый анализ.