Как я могу переименовать фотографии, учитывая данные EXIF?

Форматирование файловой системы может также быть быстрее, чем комната-rf'ing это. Особенно, если у Вас есть тысячи маленьких файлов для стирания. Кэш сквида Вы хотите полностью воссоздать... тонны файлов изображений, что Ваша потребность в обработке, но может быть выброшена после того, как конечный результат создается. файлы .obj от огромных компиляций... и т.д.

14
12.10.2012, 02:02
8 ответов

Вы можете к нему для всех файлов с помощью для цикла (в оболочке/в сценарий оболочки):

for i in *.JPG; do
  j=`jhead "$i" | grep date | sed 's/^File date[^:]\+: \(.\+\)$/\1/'`.jpg
  echo mv -i "$i" "$j"
done

Это - просто очень простая схема. Удалить echo когда Вы проверили, что все работает как ожидалось.

10
27.01.2020, 19:50
  • 1
    Спасибо. Теперь, grep дал бы мне File date : 2011:02:03 20:25:09. Как я могу отфильтровать только второй столбец? –  Tomas 07.02.2011, 00:27
  • 2
    Таким образом, я только переименовываю файл, поскольку 20:25:09 файловых систем –  Tomas 07.02.2011, 00:36
  • 3
    @Tomas, обновленный ответ - если Вы действительно только хотите время (что относительно коллизий затем?) необходимо изменить регулярное выражение, конечно. –  maxschlepzig 07.02.2011, 00:45
  • 4
    j=`jhead "$i" | grep date | sed 's/.* //'`.jpg вместо этого? –  frabjous 07.02.2011, 00:45
  • 5
    @maxshlepzig: Спасибо, Вы пропустили a ' перед ''.jpg' –  Tomas 07.02.2011, 00:50

Просто найденный здесь, что jhead может сделать все это для Вас!:)

jhead -autorot -nf%Y-%m-%d_%H-%M-%S *.jpg
28
27.01.2020, 19:50
  • 1
    Да! Но остерегайтесь той конкретной строки формата, потому что она даст два файла, взятые в ту же секунду то же имя. %i (или %03i, конкретно), даст порядковый номер, согласно просьбе в исходном вопросе. Объединение обоих не могло бы быть плохой идеей. –  mattdm 21.03.2011, 19:21

Если кому-то нужно более сложное переименование, например, для включения ключевых значений экспозиции в имя файла, вот мой небольшой сценарий. Он переименовывает jpeg-файлы на что-то подобное: NightSky_2014.08.27_22.30.05_NX20_F2.8_f20.0mm_20s_ISO800.jpg.

#!/bin/bash

for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;} 
/Exposure time:/ { e=$3; 
                   if (e==int(e)) e=int(e); 
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; } 
                 }
/ISO equiv./     { iso="ISO" $4; } 
/Focal length/   { f="f" $4; } 
/Date.Time /     { d=$3 "_" $4; gsub(":",".",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); } 
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso ".jpg"; }'`

 echo mv $s $x
 mv $s $x
 echo =====
done
0
27.01.2020, 19:50

Мне понравился код, размещенный maxschlepzig, но, тем не менее, у меня были трудности с выводом.

Проблема заключалась в пробеле в результирующем имени файла (между строкой даты и строкой времени). Хотя это и тривиально для любого, кто использует GUI, это несколько усложняет работу с файлами в командной строке.

Здесь команда 'sed' была существенно изменена на четыре отдельные операции 'sed' в пользу предыдущего монолитного аргумента. Следующее, как мне кажется, также изменяет файл на обычные 644 разрешения.

for i in *.JPG ; do
  chmod 644 $i
  j=`jhead "$i" | grep ^Date/Time | sed -e 's/^Date\/Time[ ]\+: //;s/:/-/g;s/ /_/g':/-/g;s/ /_/g'`.jpg
  echo mv -i "$i" "$j"
  # mv -i "$i" "$j"
done
0
27.01.2020, 19:50

Поскольку с этим проще иметь дело (imho), я написал сам сценарий Ruby:

require 'fileutils'

ARGV.each { |file|
  if File.exist?(file) && !File.directory?(file)
    exif = `exiftool "#{file}" | grep -E "(Error|Create Date)"`
    if exif.strip.size > 0
      exif = exif.split("\n")[0].split(/\s+/)
      if exif[0] != "Error"
        # Change the target format here
        filename = exif[3].gsub(":", "-") + " " + 
                   exif[4].gsub(":", ".") + 
                   File.extname(file)
        if filename != file && !File.exist?(filename)
          FileUtils::mv(file, File.dirname(file) + "/" + filename)
        end
      end
    end
  end
}

Что он делает?

  1. Итерирует по всем файлам передается как параметры (например, *. JPG ).

    Я проверил, правильно ли он обрабатывает файлы и видео в формате RAW. Он должен работать со всем, с чем может иметь дело exiftool .

  2. Ничего не делает, если файл

    • не существует,
    • - это каталог,
    • не имеет даты EXIF, или
    • exiftool сообщает об ошибке, или
    • файл с целевым именем уже существует.

Это делает его довольно надежным. В частности, никакие файлы не могут исчезнуть (молча), как в случае с некоторыми другими ответами.

0
27.01.2020, 19:50

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

exiv2 - это программа для чтения и записи метаданных Exif, IPTC, XMP и комментариев к изображениям, которая может читать многие теги производителей-производителей. Программа дополнительно переключается между тегами Exif, свойствами XMP и наборами данных IPTC

Таким образом, это переименовывает все JPEG в текущей папке:

for i in *.JPG; do exiv2 -v -r '%Y%m%d.%H%M%S.:basename:' rename "$i"; done

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

exiftool '-filename<${gpslatitude;} ${gpslongitude} ${datetimeoriginal}' -d "%Y-%m-%d %H.%M.%S%%-c.%%e" *.JPG
0
27.01.2020, 19:50

Мне нравится решение @Kevin, поскольку я также хотел сохранить исходное имя (чтобы избежать проблем с изображениями, сделанными в одну и ту же секунду ), вот мое решение:

for i in *.JPG; do jhead -nf%Y%m%d_%H%M%S_"$(basename "$i".JPG)" "$i" ; done
0
27.01.2020, 19:50

Первое сообщение от новичка... Первый bash-скрипт... Мне понравилось решение Libor/HalosGhost выше, так как оно включало больше деталей в переименовании. Но после тестирования повторяющиеся имена файлов в конечном итоге приводили к потере файлов. Поэтому я добавил тег счетчика в конец имени файла для удобства поиска и предотвращения коллизий. Я уверен, что кто-то здесь может улучшить это, но подумал, что это может помочь.

Приношу извинения за публикацию кода. У меня проблемы с интерфейсом, но если бы кто-нибудь мог указать мне правильный способ ведения дел, это было бы здорово.

#!/bin/bash

y=1
for s in *.jpg *.JPG
do
 echo $s
 x=`jhead "$s" | \
 awk 'BEGIN { cmt=""; }
/Camera model/   { c=$4$5$6;}
/Exposure time:/ { e=$3;
                   if (e==int(e)) e=int(e);
                   if (e<1) {e=int(0.5+1/e); e="1T" e "s";} else { e=e "s"; }
                 }
/ISO equiv./     { iso="ISO" $4; }
/Focal length/   { f="f" $4; }
/Date.Time /     { d=$3 "_" $4; gsub(":","",d); }
/Aperture /      { ap=$3; gsub("f/","F",ap); }
/Comment  /      { cmt=$3 "_"; }
END { print cmt d "_" c "_" ap "_" f "_" e "_" iso "_" ; }'`

 echo mv $s "$x${y}.jpg"
 mv $s "$x${y}.jpg"
 y=$((y+1))
 echo =====
done
0
27.01.2020, 19:50

Теги

Похожие вопросы