Переименуйте JPEG, добавив префикс в соответствии с датой
У меня есть папка с фотографиями, снятыми разными камерами, и все эти изображения имеют правильный набор тегов DateTimeOriginal EXIF.
Предположим, список файлов выглядит так:
20150831_153712.jpg
IMG_5246.JPG
IMG_5247.JPG
20150902_201425.jpg
Теперь я хотел бы знать, как переименовать эти файлы таким образом, основываясь на теге DateTimeOriginal, конечно:
001_IMG_5246.JPG
002_20150831_153712.jpg
003_IMG_5247.JPG
004_20150902_201425.jpg
По сути, я хочу, чтобы exiftool (или пакетная программа Windows, если это невозможно напрямую) сортирует всю папку JPEG по возрастанию DateTimeOriginal, а операция переименования должна ставить префикс счетчика перед именем файла (таким образом, сохраняя исходное имя файла).
Я также хотел бы, как сделать тестовую команду для предварительного просмотра переименования, прежде чем оно произойдет (чтобы увидеть, если что-то не так, я полагаю, с помощью тега TestName).
2 ответа
Предметы, которые вы хотите использовать с ExifTool - это -FileOrder
варианты и FileSequence
тег, плюс немного Perl, используя опцию расширенного форматирования. Параметр FileOrder будет сортировать файлы по времени, указанному в списке с помощью параметра. Это немного замедляет ExifTool, потому что он должен читать каждый файл дважды, но обычно все же быстрее, чем другие опции, такие как циклы и вызов ExifTool для каждого цикла. Тег FileSequence является внутренним для ExifTool и отслеживает номер обрабатываемого файла. Он начинается с 0, поэтому нам нужно добавить 1 к нему в расширенной обработке. Это также, где мы добавим нули, так что это будет как минимум 3 символа.
Попробуйте эту команду:ExifTool "-TestName<${FileSequence;$_=0 x(3-length($_+1)).($_+1)}_$filename" -FileOrder DateTimeOriginal DIR
Если это работает, просто замените -TestName
с -FileName
:ExifTool "-FileName<${FileSequence;$_=0 x(3-length($_+1)).($_+1)}_$filename" -FileOrder DateTimeOriginal DIR
Чтобы изменить количество дополняемых нулей, измените 3 в 3-length
на номер, который вы хотите. Чтобы изменить начальный номер, измените 1 в $_+1
,
Я проверил пару инструментов переименования. Основная проблема в том, что такие инструменты, как Rename Master и ExifTool, могут получить доступ к данным EXIF. Но я не смог найти способ создать нумерованный список.
Поэтому я написал сценарий PowerShell для этого. Я прокомментировал каждую строку. Это должно быть легко понять. Просто прочитайте их.
Первое, что мне нужно было сделать, это поиск по идентификатору "DateTimeOriginal", чтобы мы могли использовать GetPropertyItem(MyExifID)
, Во-вторых, мы добавляем в массив все изображения из заданной папки, которые на самом деле имеют DateTimeOriginal. Отсюда было легко. Мы сортируем столбец массив по дате, увеличиваем простой счетчик и строим наше новое имя файла с шаблоном 000_oldname
,
Этот скрипт ничего не изменит. Это только выводит что-то вроде:
Используйте его, чтобы проверить, что будет делать скрипт. После того, как вы проверили возможные результаты, удалите индикатор комментария #
до линии #Rename-Item $_[0].Fullname $newName
, Отныне скрипт будет переименовывать ваши файлы соответственно.
RenameFromExif.ps1
# Set image folder to process
$strDirectory = "T:\Pictures"
# Create empty array
$arrSortMe = @()
# Load Windows library to access EXIF data
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# Loop through all JPGs and JPEGs in the given image folder
Get-ChildItem -Path "$strDirectory\*" -Include *.jpg,*.jpeg | ForEach {
# Load current image into Powershell as bitmap object
$img = New-Object -TypeName system.drawing.bitmap -ArgumentList $_.FullName
# Error handling for images which doesn't have the specified EXIF data
Try {
# Get EXIF data with ID 36867 - which is "DateTimeOriginal"
$intExif = [Byte[]]$img.GetPropertyItem(36867).Value
# Release image or else later we can't rename it
$img.Dispose()
# Convert EXIF data from byte array to string
$strExif = [System.Text.Encoding]::Default.GetString($intExif, 0, $intExif.Length-1)
# Convert EXIF data from string to datetime
$dateExif = [DateTime]::ParseExact($strExif, 'yyyy:MM:dd HH:mm:ss', $null)
# Add to multidimensional array: [0]=current_file and [1]=datetime
$arrSortMe += ,@($_, $dateExif)
}
Catch {}
}
Write-host "DateTimeTaken" `t`t`t "New Name" `t`t`t "Old Fullname"
# Sort array by datetime and pipe the sorted array to a foreach loop
$arrSortMe | Sort-Object @{Expression={$_[1]} } | ForEach {$i=0}{
# Increment a simple counter starting with 0, so the first image gets the "1"
$i++
# Format the counter to 3-digits, append an underscore followed by the old image name
$newName = $i.ToString("000") + "_" + $_[0].Name
# Don't rename images which already have three digits as filename start
If ($_.Name -notmatch "^[\d]{3}_") {
#Rename-Item $_[0].Fullname $newName
}
# Only for debugging
Write-host $_[1].Date `t $newName `t $_[0].Fullname
}
# Clear all variables. System variables are readonly so we don't mind using * to get all
Remove-Variable * -ErrorAction SilentlyContinue
Использованные ресурсы
- http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html
- http://blogs.technet.com/b/jamesone/archive/2007/07/13/exploring-photographic-exif-data-using-powershell-of-course.aspx
- http://blog.cincura.net/233463-renaming-files-based-on-exif-data-in-powershell/
- http://www.happysysadm.com/2011/01/multidimensional-arrays-in-powershell.html
- http://www.orcsweb.com/blog/james/fun-with-powershell-sorting-multidimensional-arrays-and-arraylists/
- http://blogs.technet.com/b/heyscriptingguy/archive/2008/06/02/hey-scripting-guy-how-can-i-use-leading-zeroes-when-displaying-a-value-in-windows-powershell.aspx