Оптимизация фотоархива с помощью find и mv.

В этом видео:
– уникальное имя для каждого фото и видео;
– сортировка файлов по годам с использованием find и mv

===================
Disclaimer.
Ваши фото это уникальная вещь, по-этому не забудьте сделать бекап перед всеми манипуляциями, например, на внешнем диске.
===================
Когда речь заходит о домашнем фото-видео архиве часто бывает лень разгребать все имеющиеся материалы, вычищать дубликаты или просто плохие фото. Бывает ситуация когда одни и тебе фото лежат в нескольких папка – вы могли их просто несколько раз скопировать на диск с телефона или фотоаппарата. Решительно удалять личные фото непросто – эти фото только ваши и в Интернете их снова не скачаешь, а если и скачать можно, например, из Вконтакта, то в худшем качестве. По этому фото копятся и лежат разрозненно на разных дисках и директориях. Но настало время всё упорядочить! Или хотя бы сделать несколько правильных шагов в этом направлении.
Я произвёл экспорт своего фотоархива, а это около 128ГБ из своего фотоменеджера iPhoto на OSX. Хочу поделиться несколькими полезными на мой взгляд наработками которые можно применять независимо от вашего файлового менеджера или на сколько разрозненны у вас файлы.

Моей целью было получение отсортированных файлов с точностью до месяца. Т.е должны быть директории года, в каждой из директорий должны быть поддиректории с месяцами. Такую структуру легко хранить и можно переносить в облако да и просто хранить на внешних дисках. Я не делал какого-то универсального скрипта – просто набор полезных команд, мелких скриптов и тп. Задача обработки всех имеющихся фотографий единовременная и тратить на это много времени на изобретение супер скрипта и его отладку нет смысла.

Доступное место на дисках или в облаках постоянно дешевеет – например, сейчас можно арендовать 1ТБ в месяц на Yandex диске за 200р. 1ТБ!
По-этому я не буду выискивать дубликаты. Дубликаты имеют одинаковые имена, что логично, и при объединении директорий их можно автоматически удалить. Но может возникнуть ситуация с файлами с одинаковыми именами – например, полученными с разных устройств или одинаковые имена получились по какой-либо другой причине – терять файлы нельзя.
Получаем первую задачу – взять все файлы и выдать каждому уникальное имя.
Это можно сделать разными способами. Я выбрал следующее решение:
– Брать оригинальное имя файла и к нему прибавлять текущее Unix время, от начала unix эпохи – достаточное большое число и постоянно растущее, что помогает избавиться от необходимости самому писать счётчик.
Так как система может обрабатывать больше одного файла за единицу времени- дискретизации,
– я ещё прибавляю случайное число из глобальной переменной $RANDOM. Файлы должны теперь иметь уникальные имена, даже если я их все объединю в одну директорию и продолжу добавлять вновь отснятый материал в будущем.

Делаю я это следующим командой:
find . -name '*.JPG*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.JPG' {} \;
Ищу все файлы по шаблону – с расширением JPG, далее прибавляю текущую Unix дату и случайное число взятое из переменной RANDOM. Находиться нужно при этом в корневой директории с вашими фотками, чтобы скрипт отработал правильно. Для это сначала нужно перенести все разрозненные директории с фотографиями в одну(просто одна директория где будут собраны все директории с вашими фото). Или просто проделать эту операцию в каждой директории где у вас лежат фото. На внешних дисках и тп.
Так же, если у вас какие-либо фото с другими расширениями, например, PNG или видео с расширением MOV, то нужно соответственно переименовать и эти файлы. По этому лучше собрать все директории в одной или просто записать эти команды и делать copy-past.
find . -name '*.JPG*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.JPG' {} \;
find . -name '*.jpg*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.JPG' {} \;
find . -name '*.PNG*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.PNG' {} \;
find . -name '*.png*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.PNG' {} \;
find . -name '*.MOV*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.MOV' {} \;
find . -name '*.mov*' -exec bash -c 'mv "$0" "$0"-$(date +%s)-$RANDOM.MOV' {} \;

*Опционально. Можно перенести все файлы из поддиректорий в текущую директорию:
find . -type f -exec bash -c 'mv "$0" ./' {} \;

После того как все файлы имеют уникальные имена настало время их как-то отсортировать – я сортирую по годам и месяцам.
Вообще у меня файлы уже были отсортированы при экспорте моим фотоменеджером – файлы хранились в директориях с датами их создания с точностью до дня. Я сортировал по именам. Но если у вас полный хаос или директории названы как-нибудь ‘фото с отпуска’ или “от Васи”, то сортировать придётся по дате их модификации – обычно мы делаем фото и храним их, не меняем. Конечно, если вы что-то делаете с фото-меняете размер, улучшаете цвета, то найти точную дату будет непросто, но в таком случае файлы у вас скорее всего уже как-то отсортированы.

Увеличивая параметр mtime утилиты find можно отсортировать все ваши файлы от самых старых к самым новым – перемещая найденные файлы в нужные директории, например, отсортировать по годам.
Например, сегодня 3 апреля. С начала года прошло 93 дня. Файлы созданные ранее 2000 года будут иметь дату больше 5933.
Отсортировав самые старые файлы, приступаем к более ранним – отнимаем количество дней в 2000 году (366 – високосный год) и получаем все файлы созданные в 2000м и так далее.
$ find ./allphoto -type f -mtime +5933 -exec bash -c 'mv "$0" ./2000-older' {} \;
$ find ./allphoto -type f -mtime +5567 -exec bash -c 'mv $0 ./2000' {} \;

Отсортировав файлы по годам, можно отсортировать их и по месяцам уже внутри каждой директории.
Операция достаточно нудная, но делать её придётся всего один раз.

Если у вас имеющиеся директории имеют имена с указанием дат, как у меня, то операция будет проще.
Я применял, следующий набор команд для полной сортировки по года и месяцам. Такой случай был у меня, вероятно попадётся и ещё кому-то.
Отсортировать все директории по годам:
mv ./*2000*/* 00/
mv ./*2001*/* 01/
...
mv ./*2015*/* 15/
mv ./*2016*/* 16/

Далее переходим в директории с годами и сортируем по месяцам:
cd “~/2000”
mv ./*января*/* ./2000.1
mv ./*февраля*/* ./2000.2
mv ./*марта*/* ./2000.3
mv ./*апреля*/* ./2000.4
mv ./*мая*/* ./2000.5
mv ./*июня*/* ./2000.6
mv ./*июля*/* ./2000.7
mv ./*августа*/* ./2000.8
mv ./*сентября*/* ./2000.9
mv ./*октября*/* ./2000.10
mv ./*ноября*/* ./2000.11
mv ./*декабря*/* ./2000.12

В подобной ситуации нужно будет вынуть все файлы из поддиректорий с месяцами. Зависит от количества ваших поддиректорий. Возможно будет проще ограничиться директориями с названиями месяцов, чтобы просто сделать copy-past нескольких команд в директории с каждым из годов.
Когда вы это закончите с сортировкой – просто удалите все лишнии директории, они должны быть уже пустыми.

Описаная мной задача достаточно простая, но если объём файлов большой, то без использования shell команд с нужными ключами может занять у вас не один день и вы можете в какой-то момент всё это бросить.

Надеюсь вам поможет это видео и домашняя фототека у вас будет упорядочена.

На этом всё.
Удачи!

Полезные ссылки:
Difference between mtime, ctime and atime