Полезное⚜️
December 22, 2024
Замена даты создания файла на exif
Несколько лет назад я потерял все свои фотографии, которые хранил на внешнем жестком диске. Для упорядочивания файлов было написано несколько скриптов, и этот один из них.
Скрипт ищет дату создания фотографии (её проставляет фотоаппарат) и подставляет в поле "создано".
Важно: Для работы со свойствами EXIF в PowerShell используется класс[System.Drawing.Bitmap], являющийся частью .NET Framework. Однако в некоторых современных версиях PowerShell этот класс может быть не доступен по умолчанию.
Если при запуске скрипта возникнут ошибки, убедитесь, что у вас установлена .NET Framework (Windows PowerShell 5.1 обычно идет вместе с .NET Framework) или используйте другой способ чтения EXIF (например, утилитуexiftool).
#requires -version 3
<#
.SYNOPSIS
Скрипт рекурсивно ищет файлы изображений, получает EXIF-дату (дата/время съемки)
и ставит её в качестве даты создания файла. Если EXIF не найдена – выводит имя файла в консоль.
.DESCRIPTION
1. Рекурсивно обходит все подпапки в указанных путях (по умолчанию - текущая директория).
2. Ищет файлы изображений по заданным расширениям: jpg, jpeg, png, gif, tiff, bmp.
3. С помощью .NET-класса [System.Drawing.Bitmap] считывает EXIF-свойства.
4. Берёт значение EXIF-тега DateTimeOriginal (Id 0x9003), парсит его в дату и
назначает её как CreationTime и LastWriteTime файла.
5. Если EXIF-дата отсутствует, выводит сообщение в консоль и ничего с файлом не делает.
.NOTES
Автор: ChatGPT (пример)
Требования:
- PowerShell 3.0+
- .NET Framework (для класса System.Drawing.Bitmap)
#>
param(
[Parameter(Mandatory=$false, Position=0)]
[string]
$Path = "."
)
# Подключаем сборку System.Drawing, если она ещё не загружена.
# В некоторых окружениях (например, Windows PowerShell 5.1) достаточно, в других может быть недоступна.
try {
Add-Type -AssemblyName System.Drawing
}
catch {
Write-Host "Не удалось загрузить сборку System.Drawing. Убедитесь, что установлена .NET Framework или попробуйте другой метод чтения EXIF." -ForegroundColor Red
return
}
# Список расширений, которые считаем изображениями
$imageExtensions = '.jpg', '.jpeg', '.png'
# Получаем список всех файлов с нужными расширениями рекурсивно из каталога $Path
Write-Host "Поиск изображений в папке: $Path`..."
$files = Get-ChildItem -Path $Path -Recurse -File | Where-Object {
$imageExtensions -contains $_.Extension.ToLower()
}
if ($files.Count -eq 0) {
Write-Host "Не найдено файлов с расширениями: $($imageExtensions -join ', ')"
return
}
foreach ($file in $files) {
try {
$bitmap = New-Object System.Drawing.Bitmap($file.FullName)
# Ищем EXIF-тег DateTimeOriginal (0x9003).
# Для некоторых снимков старых форматов может использоваться 0x0132 (DateTime) или 0x9004 (DateTimeDigitized).
# Но самый распространённый - 0x9003 (DateTimeOriginal).
$exifItem = $bitmap.PropertyItems | Where-Object { $_.Id -eq 0x9003 }
if ($exifItem) {
# EXIF-дата хранится как ASCII-строка формата "yyyy:MM:dd HH:mm:ss"
$exifDateString = [System.Text.Encoding]::ASCII.GetString($exifItem.Value).Trim([char]0)
if ([string]::IsNullOrWhiteSpace($exifDateString)) {
Write-Host "EXIF-дата отсутствует (пустая) в файле: $($file.FullName)"
$bitmap.Dispose()
continue
}
# Парсим дату. Формат обычно: "YYYY:MM:dd HH:mm:ss"
$format = "yyyy:MM:dd HH:mm:ss"
$exifDate = [datetime]::ParseExact($exifDateString, $format, $null)
# Устанавливаем дату создания (CreationTime) и дату изменения (LastWriteTime) файла
[System.IO.File]::SetCreationTime($file.FullName, $exifDate)
[System.IO.File]::SetLastWriteTime($file.FullName, $exifDate)
# (опционально) Можете оставить только CreationTime или только LastWriteTime
# [System.IO.File]::SetCreationTime($file.FullName, $exifDate)
Write-Host "Обновлена дата для: $($file.FullName) => $exifDate"
}
else {
Write-Host "EXIF-дата не найдена в файле: $($file.FullName)"
}
$bitmap.Dispose()
}
catch {
Write-Warning "Ошибка при обработке файла $($file.FullName). Текст ошибки: $_"
}
}
Для запуска надо сохранить скрипт в файл, например в Set-ExifDate.ps1. Пример команды для запуска:
.\Set-ExifDate.ps1 -Path "C:\MyPhotos"