- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF143:exiftools
Материал из Linuxformat.
- ExifTool Приведите свои фото в порядок нашими удобными скриптами
Содержание |
ExifTool: Фото по полочкам
- Беспорядок в фотографиях может причинить вам немало беспокойства, отчего и захворать недолго. К счастью, Марко Фиоретти нашел лекарство.
Не так давно фотографии представляли собой карточки из глянцевой бумаги с цветными пятнами на них, которые с годами бережно накапливались в картонных коробках и красивых альбомах. Сегодня появление доступных цифровых фотокамер привело к тому, что каждый год мы можем делать сотни или тысячи новых снимков. Несмотря на то, что они цифровые, их тоже нужно хранить.
Утилиты, подобные Digikam, несмотря на свои возможности, не самый лучший вариант для организации хранилища. Поэтому в этом руководстве я решил поделиться с вами полуавтоматической технологией, которая позволит переименовать и отсортировать фотографии и поместить их в архив. В ее основе – утилита ExifTool и два простых скрипта. Все это вы найдете на нашем диске. Для работы с ними необходимо только общее представление, что такое скрипты и как они работают.
Какова роль скриптов?
Мои скрипты делают очень немногое, но если делать это вручную, уйдет масса вашего времени. Во-первых, они переименовывают файлы, помечая каждый из них датой. Затем они автоматически сохраняют каждую фотографию в каталоги, которые также иерархически разбиты по годам, месяцам и дням. С их помощью также можно добавить комментарии, рейтинги и метки к вашим фотографиям. Эти задачи часто лучше решают графические программы вроде Digikam, но если сначала упорядочить вашу коллекцию, то это сэкономит вам массу времени.
А кроме того, ими довольно просто пользоваться, если вы знаете, что у них внутри, и имеете некоторое представление о метаданных фотографий. По правде говоря, самое сложное в данной статье – это не понять, как работают скрипты, а уяснить, почему они должны делать то или иное.
Начинаем с хаоса
Итак, однажды вы проснулись и решили создать одну, тщательно упорядоченную цифровую коллекцию всех цифровых и бумажных фотографий, которые вам не безразличны. Делать это вручную – дело не просто долгое, но и безнадежное. Вероятно, вы столкнетесь со следующими задачами, в любом сочетании: первая – оцифровка бумажных фотографий, что скучно и требует времени, но несложно. Чтобы сделать все быстрее, можно сканировать по четыре фотографии за один раз с любым сканером формата A4 и сохранять результаты в файлах с уникальными именами – способ, описанным мной в LXF123.
Другая очевидная необходимость – разобраться во всех фотографиях, которые прислали друзья. Они могут быть сделаны разными камерами или даже такой же камерой, как у вас. В первом случае на диске появятся файлы со всеми известными человечеству и поэтому несовместимыми схемами именования. Сотни файлов будут иметь имена вроде XYZ_001.JPG, ..., XYZ_153.JPG, а другие – имена вроде P00001.jpeg, ..., P99999.jpeg; и т. д. Если вам не повезет и у друзей найдется аналогичная камера, есть риск получить несколько файлов с одинаковыми именами, перезапись которых обернется катастрофой, если не проявить должного внимания.
Наихудший сценарий появляется в случае объединения самых досадных характеристик двух вышеупомянутых проблем. В этом случае вы получаете файлы отсканированных фотографий во всех графических форматах, открытых со времен изобретения транзистора. Более того, в их именах не будет и следа пользы или смысла. Наверное, кто бы ни прислал вам эти файлы, он подсознательно вас ненавидит.
Поименовать всю эту неразбериху – наша первая задача. В конце концов, унифицированные имена файлов – основное условие для эффективной и портируемой системы управления фотографиями. Для этого есть несколько критериев, и главный из них в том, что фотографии должны остаться в отдельных файлах на диске в стандартных форматах. Если зарыть фотографии в глубинах базы данных, производительность улучшится, но этот вариант ни в коем случае не подходит, если вы хотите иметь возможность просто делать резервные копии, а также дальше укреплять коллекцию.
По похожим причинам, а также потому что имена файлов должны быть уникальны, избегайте в именах файлов символов, не являющихся буквами и цифрами. Описательные названия тоже не подходят – названия типа Мамин_выпускной.jpg могут иметь смысл сегодня, но с годами вы будете мучительно вспоминать: «От чьей это мамы? Моей или моей второй половинки?» А как насчет возрастающей нумерации? О, нет. Она перестанет возрастать, а стало быть, иметь смысл, когда придется добавить фотографии в уже существующий альбом. Нет, наиболее переносимая, масштабируемая и защищенная на будущее схема именования файлов – давать каждому файлу имя в соответствии с точным временем его создания. Файлы с именами вида YYYYMMDDHHMMSS переносимы; имена не слишком длинные; их всегда можно отсортировать по дате в любой программе, даже если добавить или удалить фотографии из альбома; и из них очень удобно делать резервные копии, отсортированные в хронологическом порядке. Если поместить все фотографии, снятые в определенный день или в определенный месяц в один каталог с таким именем, как Year/Month или YearMonth, это только упростит индексирование.
Теперь, определившись со схемой именования файлов, поговорим о метаданных, то есть о дополнительной информации по каждой фотографии. В них может храниться почти все что угодно: от автора и копирайта до установок камеры или меток категорий. Существует три основных стандарта метаданных фотографий, но мы сосредоточимся на наиболее распространенном варианте – фотографии в формате JPEG с метаданными EXIF (Exchangeable Image File Format).
Метаданные фотографии могут храниться либо в файле (как это происходит с EXIF), либо в базе данных. Первый подход гарантирует, что они не будут утеряны при переносе фотографий. Второй значительно ускоряет поиск и другие операции. Лично я пользуюсь обоими подходами сразу: сначала записываю метаданные в формате EXIF в файлы, затем, открывая свои альбомы в Digikam, копирую эту информацию во внутреннюю базу данных.
Используем скрипты
Теперь перейдем к конкретному примеру – к ситуации, показанной на экранном снимке выше. Здесь есть несколько фотографий в различных форматах, которые нужно упорядочить, разобрать и опознать. Обратите внимание, что для ясности примера в нашем каталоге содержится только четыре файла фотографий (и один текстовый файл, назначение которого мы проясним чуть позже), но скрипт будет работать и с тысячами файлов. Некоторые из изображений – даже не фотографии, а просто случайные экранные снимки. Я сделал это намеренно, чтобы проиллюстрировать работу скриптов. При необходимости любую картинку можно преобразовать в нечто гораздо более полезное – файл, с которым будет работать любой менеджер фотографий (с метаданными и со всем остальным), как если бы этот файл был снят цифровой камерой.
Вот как работает скрипт: для начала он помещает все файлы, которые нужно отсортировать, в специально созданный для этого каталог. Затем – и это единственное, что вам придется сделать вручную – надо подготовить простой текстовый файл notes_file.txt.
Он необходим потому, что мы переименовываем, сортируем и архивируем фотографии на основе времени их создания. Для цифровых фотографий эти данные находятся в тэге EXIF под названием DateTimeOriginal. Во всех остальных случаях мы должны предоставить примерное значение. Эти значения мы и записываем в файл notes_file.txt:
$ cat notes_file.txt joe.jpg | 2001:01:01 Mom.JPEG | 1998:12:01 Mike.png Dad.tiff | 2005:03:28
Как видите, нужно только написать имена всех файлов фотографий, которые находятся в каталоге, по одному в каждой строке. Добыть их список можно командой ls -l | cut -c45‑ > notes_file.txt. Затем добавьте после символа | время создания каждой фотографии в формате YYYY:MM:DD. Если в соседних строках есть два или более файлов с одинаковыми датами, добавьте дату только к первому из них. Когда все будет готово, запустите в командной строке скрипт, передав ему полный путь к этому каталогу в качестве первого и единственного аргумента:
$ photo_archiver.sh $HOME/lxf_demo
Работу скрипта с каждым файлом отражает алгоритм, приведенный на рисунке.
Разбираем скрипт
Первое, что мы делаем – сохраняем исходную версию файла, делая рабочую копию. Затем, при необходимости, эта копия преобразуется в формат JPEG, так как нам нужен формат, позволяющий хранить тэги EXIF. Для этого мы пользуемся утилитой convert, входящей в состав пакета ImageMagick (http://www.imagemagick.org):
convert /tmp/my_tmp_photo /tmp/my_tmp_pic.jpg
Затем мы обрабатываем тэги EXIF с помощью ExifTool:
1 DATE=`exiftool -s -f -DateTimeOriginal /tmp/my_tmp_pic.jpg | cut -d: -f2-` 2 3 if [ “$DATE” == “ -” ] 4 DATE_FROM_NOTES=`$RETRIEVE_DATE notes_file.txt $PIC` 5 if [ “$DATE_FROM_NOTES” == “NO_DATE_FOUND” ] 6 then 7 echo “NO_DATE_FOUND for $PIC, sorry!” 8 exit 9 else 10 exiftool -DateTimeOriginal=”$DATE_FROM_NOTES 12:00:00” /tmp/my_tmp_pic.jpg 11 fi 12 fi
В первой строке ExifTool получает параметр EXIF под названием DateTimeOriginal из файла JPEG и сохраняет его, удалив все пробелы и ненужные фрагменты, в переменной $DATE. Если в результате этой операции мы получаем пустую дату, мы просим retrieve_date_from_file.pl (он есть на нашем DVD) извлечь подходящую дату из файла notes_file.txt. Затем с помощью ExifTool мы записываем это значение в файл JPEG. Обратите внимание, что скрипт всегда устанавливает одно и то же время (12:00:00). Если вам нужна большая точность, введите более точную дату в notes_file.txt и измените второй вызов ExifTool соответствующим образом.
Теперь у нас появился файл в формате JPEG my_tmp_pic.jpg, который содержит дату съемки в переменной EXIF DateTimeOriginal. Затем выполняется следующая часть скрипта:
1 NEWDATE=`exiftool -s -f -DateTimeOriginal /tmp/my_tmp_pic.jpg | cut -d: -f2- | tr -d “ :”` 2 PARTIAL_DATE=`echo $NEWDATE | cut -c1-12` 3 SECNDS=`echo “$NEWDATE” | cut -c13-14` 4 mv /tmp/my_tmp_pic.jpg /tmp/$NEWDATE.jpg 5 touch -t “$PARTIAL_DATE.$SECNDS” /tmp/$NEWDATE.jpg
Сначала мы опять считываем дату, ликвидируем все пробелы и двоеточия (команда tr -d в конце первой строки) и называем результат $NEWDATE. Формат этой переменной – YYYYMMDDHHMMSS. Первые 12 символов этой строки, определяющие дату и время с точностью до минуты, записываются в $PARTIAL_DATE. Два последних символа, секунды, записываются в переменную $SECNDS. Скоро вы поймете, зачем это нужно.
Причина, по которой мы создали переменную $NEWDATE, очевидна из четвертой строки приведенного фрагмента: эта переменная нужна, чтобы переименовать временный файл в $NEWDATE.jpg. В пятой строке происходит последняя часть не такой уж и черной магии – в ней в то же значение устанавливается время создания файла командой touch. К сожалению, эта утилита распознает секунды только после точки. Поэтому нам пришлось создавать отдельно $PARTIAL_DATE и $SECNDS. В итоге после выполнения скрипта Mom.JPEG превращается в 19981201120001.jpg:
$ ls -l 19981201120001.jpg -rw-rw-r-- 1 marco marco 61909 Dec 1 1998 19981201120001.jpg $ exiftool -s -f -DateTimeOriginal 19981201120001.jpg | cut -d: -f2- | tr -d “ :” 19981201120000
Понятно, что я имел в виду? Теперь у нас есть файл, чьи имя, время создания и дата съемки полностью совпадают с EXIF! Последнее, что делает скрипт photo_archiver.sh – помещает каждую фотографию в каталог с подходящим именем, создавая его, если такого еще нет:
1 YEAR=`echo $NEWDATE | cut -c1-4` 2 MONTH=`echo $NEWDATE | cut -c5-6` 3 DAY=`echo $NEWDATE | cut -c7-8` 4 5 if [ ! -d “$BASE_PHOTO_DIR/$YEAR/$MONTH/$DAY” ] 6 then 7 mkdir -p $BASE_PHOTO_DIR/$YEAR/$MONTH/$DAY 8 fi 9 mv /tmp/$NEWDATE.jpg $BASE_PHOTO_DIR/$YEAR/$MONTH/$DAY
В первых трех строках $NEWDATE разбивается на год, месяц и день. В строках с 5 по 7 при необходимости создается каталог в соответствии с этой датой, и файл перемещается туда. В моем случае 19981201120001.jpg попадает в каталог $BASE_PHOTO_DIR/1998/12/01.
А теперь на шаг отступим и восхитимся результатами работы скрипта, показанными на экранном снимке. На левой панели мы видим, что скрипт создал правильную иерархию альбомов в каталоге $BASE_PHOTO_DIR (lxf_demo) согласно имеющимся данным EXIF и содержимому файла notes_file.txt. На центральной панели и в левом верхнем углу мы видим, что имена файлов и время их создания были изменены соответствующим образом. Наконец, на панели данных EXIF мы видим, что Digikam распознает и отображает исходную дату создания фотографии, которую скрипт прописал в EXIF.
Что еще нужно знать?
Внимательные читатели заметят в коде явную ошибку. А вдруг найдется несколько фотографий с одинаковыми значениями поля DateTimeOriginal? Не перезапишет ли каждая их них предыдущую, если все они получат одинаковые имена вида YYYYMMDDHHMMSS.jpg? Не отчаивайтесь, взгляните на экранный снимок под окончательными результатами процесса, и вы увидите, что файлов два, а не один. Дело в том, что скрипт проверяет, существует ли уже файл с таким именем, и если да, то делает грязный, но эффективный ход. Имя файла – целое число, и если файл N.jpg уже есть, скрипт сохраняет текущий файл под именем N+1.jpg.
Конечно, в нашем мире секунды все еще идут только от 0 до 59. Что делать, если найдется более 60 фотографий с одинаковым значением поля DateTimeOriginal? Все просто – у всех этих фотографий будет одинаковое корректное время создания в формате Unix (как у 19981201120001.jpg), но только у первых 60 имя файла будет соответствовать времени создания. Если это реальная, а не теоретическая проблема, код нетрудно изменить, сохранив уникальность имен, например, за счет дополнительных суффиксов вроде 19981201120001.aa.jpg, 19981201120001.ab.jpg…
Наконец, JPEG – это формат с потерей качества. Если у вас есть фотографии высокого качества, сделать их JPEG-версии очень удобно, но нужно также сохранить все исходные файлы и связать их с JPEG-копиями. Тогда – и это упражнение остается вам, потому что здесь просто не осталось на него места – нужно переименовать исходные файлы по тому же шаблону YYYYMMDDHHMMSS, но сохранить исходные расширения.
Как обобщить этот метод
Написать такой скрипт стало возможным благодаря единственному условию: способности ExifTool записывать и считывать тэги даты. Однако в метаданных EXIF можно хранить гораздо больше информации. Так как ExifTool поддерживает все параметры EXIF, с ее помощью можно автоматически устанавливать и любые другие параметры. Например, из командной строки можно добавить описание фотографии:
$ exiftool ‘-Description=this, instead, is a caption inserted with exiftool’ P1090097.JPG $ exiftool -Keywords=’Montefeltro, family’ P1090097.JPG
Возможности ExifTool на этом не заканчиваются. Я автоматически добавил к своим фотографиям широту и долготу с помощью скрипта из моего руководства по геотэггингу (в LXF112). Теперь в любой программе, поддерживающей работу с геотэгами, можно увидеть, где были сняты мои фотографии. Ну не отличная ли штука ExifTool?
Запутались?
Если вы запустили скрипт и получили не совсем то, что ожидали, не отчаивайтесь. Во-первых, Digikam – как и любой другой менеджер фотографий с базой данных – может синхронизировать изменения с тэгами EXIF не сразу. В Digikam выберите Images > Reread Metadata From Images [Изображения > Перечитать метаданные из изображений] в главном меню, и вы увидите свои изменения.
Также нужно знать, что и в EXIF, и в Digikam есть несколько тэгов с датой. Например, есть тэг, где хранится дата последнего изменения файла. Посмотрите на панель EXIF в Digikam или загляните в документацию по ExifTool, чтобы найти другие поля. Лично у меня никогда не было необходимости напрямую работать с дополнительными тэгами. Но если вы захотите это сделать, все, что нужно – добавить несколько строк в скрипт.
Как быть с пробелами?
Основной скрипт, с которым мы имеем дело, не сработает, если в именах файлов попадутся пробелы или спецсимволы. Я умышленно исключил этот вариант, потому что, отказавшись от него, любой хороший и сложный скрипт можно написать гораздо быстрее и проще, хотя и Linux, и оболочка способны разобраться с такими символами. Поэтому я никогда не храню файлы со странными именами сам и переименовываю все файлы, полученные от других, при первой же возможности. Впрочем, вам не обязательно впадать в эти крайности. Чтобы обрабатывать файлы со странными именами, просто замените строку for PIC... в моем скрипте первыми четырьмя строками скрипта, который вы найдете по адресу http://www.cyberciti.biz/tips/handling-file-names-with-spaces-in-bash.html.
Как удалить метаданные EXIF?
Запись комментариев, тэгов и другой информации в фотографии, говоря техническим языком, весьма здравый подход. Однако с точки зрения взаимоотношений он может стать губительным. Причина в том, что EXIF – всемирный открытый стандарт, и данные EXIF не шифруются. А значит, каждый, кто получит копию вашей фотографии, сможет прочесть и все ее метаданные. Запечатлеть таким образом те или иные факты из жизни – это прекрасно, и ничто вам не мешает обозначить комментарием «Лошара» портрет вашего дядюшки, но прежде чем отправлять ему фотографию по электронной почте или загружать ее на Flickr, сделайте копию и выполните следующую команду, которая очистит содержимое всех полей EXIF:
exiftool -all= uncle_portrait.jpg