2017-09-12

Файлы с фото: упорядочиваем имена

Недавно вернулся из поездки, притащил оттуда фотки аж на трёх фотоаппаратах. Так уж получилось: Honor 8 Pro хорошо умеет делать фотографии в условиях низкой освещенности и на него можно сделать селфи, Note 4 поражает четкостью и насыщенностью в нормальных условиях, но на него селфи не сделаешь (попала пыль в переднюю камеру), а Canon EOS 1100D и вовсе не телефон, а полноценная камера, хоть и старенькая, но как минимум с оптическим зумом.

Иногда в процессе съемки я делаю один и тот же снимок различными камерами, надеясь потом отобрать наиболее удачный. 

В итоге, скачанные c одной камеры файлы называются датой-временем, типа 20170830_121103.jpg, на другой - тоже самое, но с неотключаемым префиксом IMG_20170830_121103.jpg, а Canon и вовсе лепит снимки с номерами по возрастанию: IMG_5678.JPG. Как их теперь объединить в один упорядоченный по имени файловый массив, да еще и соблюсти хронологию?!... Ах да, дополнительая беда: перед съемкой я совершенно позабыл выставить на них одинаковое время... 

Ругать кроме себя некого, но можно все-таки попробовать разобраться. Мне помогла замечательная утилита exiftool из пакета libimage-exiftool-perl. Она умеет читать EXIF-информацию из файла (не только из картинок, кстати) и производить над ней несложные, но чертовски востребованные мной операции. Используем её, чтобы получить все файлы с именами типа 20170830_121103.jpg.

Итак, среди двух страниц разнообразных тегов нам нужен только CreateDate, его можно получить так:

$ exiftool -CreateDate IMG_5555.JPG
Create Date                     : 2017:09:03 15:20:01

Воспользуемся специальной опцией -d, чтобы преобразовать время как можно ближе к будущему имени файла:

$ exiftool -CreateDate -d "%Y%m%d_%H%M%S.jpg" IMG_5555.JPG 
Create Date                     : 20170903_152001.jpg

Разобьем строку на два поля по двоеточию, возьмем второе и срежем первый символ:

$ exiftool -CreateDate -d "%Y%m%d_%H%M%S.jpg" IMG_5555.JPG | awk -F':' '{print substr($2,2)}'
20170903_152001.jpg


Теперь, если переименовать все файлы по внутреннему тегу, получим единообразие, но из-за расходящегося времени снимки могут потерять хронологию и смотреть (а тем более комментировать) такое слайдшоу будет немного дискомфортно.

Не отчаиваемся! Выбираем одну из камер, которая будет "эталоном". Берем вторую, наблюдаем разницу во времени, хоть с точностью до секунды (но обычно это минуты или даже часы, из-за разных таймзон). Пусть это будет 24 минуты, например. 

Используем опцию exiftool -globalTimeShift, указывая аргументом ей это самое смещение (знак впереди указывает в каком направлении надо сдвинуть временную метку). И натравливаем нижеприводимый скрипт на файлы этой камеры:

#!/bin/bash

for fname in *.JPG; do
  newname=$(exiftool -CreateDate -globalTimeShift "+0:0:0 0:24:0" -d "%Y%m%d_%H%M%S.jpg" $fname | awk -F':' '{print substr($2,2)}')
  mv "$fname" "$newname"
done

Если камер несколько, вычисляем для каждой из них свое смещение от "эталонной", меняем в скрипте зачение аргумента -globalTimeShift и натравливаем на файлы с фотографиями.

Ура, готово! Теперь все файлы называются единообразно, упорядочены по времени, и только внутри у них в EXIF по-прежнему сохранено исходное значение.

В моем случае это не важно, но если нужно, то всемогущий exiftool может и это исправить тоже. 

man exiftool ;)