Установка атрибутов медиафайлов на основе EXIF

При загрузке на компьютер снимков с камеры мобильного телефона Apple iPhone дата модификации файлов не соответствует реальному времени съемки. С помощью утилиты exiftool и командного интерпретатора GNU/Linux ситуацию можно исправить как для файлов изображений, так и для видеофайлов.

При загрузке на компьютер снимков с камеры мобильного телефона Apple iPhone дата модификации файлов не соответствует реальному времени съемки. В поисках решения вначале я попробовал утилиту identify, которая идет в пакете libgraphicsmagick. Но оказалось, что она успешно работает только с фотоизображениями. В итоге, я остановился на утилите exiftool, которая позволяет прочесть EXIF атрибуты в файлах фотоизображений и видеороликов.

Установка EXIFtool

Ubuntu (Debian):

sudo apt install libimage-exiftool-perl

Чтение атрибутов EXIF

Утилита 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

11 июля 2018—11 июля 2018
Максим Проскурня
Источники: How can I change the date modified/created of a file?
1997–2024 Axofiber, axofiber.info