При загрузке на компьютер снимков с камеры мобильного телефона Apple iPhone дата модификации файлов не соответствует реальному времени съемки. В поисках решения вначале я попробовал утилиту identify, которая идет в пакете libgraphicsmagick. Но оказалось, что она успешно работает только с фотоизображениями. В итоге, я остановился на утилите exiftool, которая позволяет прочесть EXIF атрибуты в файлах фотоизображений и видеороликов.
Ubuntu (Debian):
sudo apt install libimage-exiftool-perl
Утилита exiftool позволяет прочитать из файлов все атрибуты блока EXIF. Для решения нашей задачи необходимы атрибуты, описывающие дату и время фото- видеосъемки. В файлах цифровой фотосъемки нам подойдет атрибут «CreateDate».
Например:
> exiftool IMG_3763.JPG | grep Create Create Date : 2017:03:06 13:06:51 Create Date : 2017:03:06 13:06:51.866 >
Утилита exiftool позволяет прочитать только конкретный атрибут, указав его сокращенное наименование «-CreateDate»:
> exiftool -CreateDate IMG_3763.JPG Create Date : 2017:03:06 13:06:51 >
Наименование данного атрибута в EXIF-блоке видеофайлов отличается. Для чтения даты съемки видеофайла необходимо указывать атрибут «-CreationDate».
> exiftool -CreationDate IMG_6532.MOV Creation Date : 2017:05:25 20:19:17+03:00 >
Для установки атрибутов времени последней модификации файла используется встроенная команда touch с атрибутом «-d». Чтобы установить корректную дату и время необходимо выполнить несколько преобразований. Во первых, надо выделить значение искомого EXIF-атрибута, а во-вторых, скорректировать форматирование записи времени. То есть, например, для фотоизображений вместо «2017:03:06 13:06:51» необходимо получить «2017-03-06 13:06:51». А для видеофайлов необходимо вместо «2017:05:25 20:19:17+03:00» получить «2017-05-25 20:19:17».
Лучше всего для этого подойдет функция поиска и замены подстрок текста с учетом регулярных выражений в потоковом текстовом редакторе sed. Для форматирования значения даты съемки фотоизображения в формат утилиты touch используется вызов sed с указанием выражения в атрибуте «-r»:
sed -r 's/Create Date[ ]+[[:punct:]] //;s/:/-/;s/:/-/;s/\+[0-9:]+$//'
Если на стандартный вход этому вызову подать результат чтения атрибута «-CreateDate», то на выходе получится запись даты и времени съемки в требуемом формате:
> exiftool -CreateDate IMG_3763.JPG | sed -r 's/Create Date[ ]+[[:punct:]] //;s/:/-/;s/:/-/;s/\+[0-9:]+$//' 2017-03-06 13:06:51 >
Аналогично надо поступить для видеофайлов:
> exiftool -CreationDate IMG_6532.MOV | sed -r 's/Creation Date[ ]+[[:punct:]] //;s/:/-/;s/:/-/;s/\+[0-9:]+$//' 2018-05-25 20:19:17 >
Поиск файлов в текущей директории выполняется командой find с указанием глубины спуска по каталогам «-maxdepth 1» — только текущая директория, и указанием типа искомых объектов «-type f» — только файлы.
find ./ -maxdepth 1 -type f
Если в каталоге окажутся не только файлы фото/видео, то необходимо их отфильтровать. Фильтрация изображений PNG, JPEG и HEIC выполняется с помощью регулярного выражения ".*\.\(jpg\|png\|heic\)$", указанного в атрибуте -iregex (без учета регистра).
find ./ -maxdepth 1 -type f -iregex ".*\.\(jpg\|png\|heic\)$"
Для фильтрации видео в контейнере MОV используется свое выражение — ".*\.\(mov\)$".
#!/bin/bash / # -- 1 -- # # find all image files in current directory if [ "$1" == "help" ] then echo "Usage: exif.to.date [path]" echo "" echo "Sets image and movie files attributes by EXIF creation date parameters." echo "Handles *.jpg, *.png and *.mpv files in current directory or in specified folder by [path] option." else if [ -n "$1" ] then echo "Entering \"$1\"" echo "Processing images..." files=$(find $1 -maxdepth 1 -type f -iregex ".*\.\(jpg\|png\|heic\)$") else echo "Entering current directory" echo "Processing images..." files=$(find . -maxdepth 1 -type f -iregex ".*\.\(jpg\|png\|heic\)$") fi for f in ${files} do touch -d "$(exiftool -CreateDate $f | sed -r 's/Create Date[ ]+[[:punct:]] //;s/:/-/;s/:/-/;s/\+[0-9:]+$//')" $f done # -- 2 -- # # find all movie files in current directory if [ -n "$1" ] then echo "Processing movies..." files=$(find $1 -maxdepth 1 -type f -iregex ".*\.\(mov\)$") else echo "Processing movies..." files=$(find . -maxdepth 1 -type f -iregex ".*\.\(mov\)$") fi for f in ${files} do touch -d "$(exiftool -CreationDate $f | sed -r 's/Creation Date[ ]+[[:punct:]] //;s/:/-/;s/:/-/;s/\+[0-9:]+$//')" $f done echo "Finished" fi