介紹如何在 Windows 中使用 PowerShell 指令稿自動根據照片拍攝日期時間重新命名檔案名稱。
取得照片拍攝日期
首先建立一個專門用來取出照片拍攝日期的 PowerShell 指令稿 exif-datetaken.ps1,內容如下:
# 取得照片拍攝日期用的指令稿
param([string]$file)
function GetTakenData($image) {
try {
return $image.GetPropertyItem(36867).Value
} catch {
return $null
}
}
[Reflection.Assembly]::LoadFile('C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Drawing.dll') | Out-Null
$image = New-Object System.Drawing.Bitmap -ArgumentList $file
try {
$takenData = GetTakenData($image)
if ($takenData -eq $null) {
return $null
}
$takenValue = [System.Text.Encoding]::Default.GetString($takenData, , $takenData.Length - 1)
$taken = [DateTime]::ParseExact($takenValue, 'yyyy:MM:dd HH:mm:ss', $null)
return $taken
} finally {
$image.Dispose()
}
這段指令稿是利用 System.Drawing 取出照片中的拍攝日期資訊。
依據日期與時間重新命名圖檔
將上面建立的 exif-datetaken.ps1 指令稿跟照片圖檔放在圖一個目錄下,並在該目錄之下執行以下 PowerShell 指令,即可自動將所有照片(*.jpg 檔案)依據拍攝日期與時間重新命名。
Get-ChildItem *.jpg | ForEach {
# 取得照片拍攝日期
$date = (.\exif-datetaken.ps1 $_.FullName)
# 檢查照片拍攝日期
if ($date -eq $null) {
Write-Host $_.Name ' 錯誤:找不到拍攝日期資訊。'
return
}
# 以日期與時間作為新檔案名稱
$fileName = $date.ToString('yyyyMMdd-HHmmss') + '.jpg'
# 顯示新舊檔案名稱
Write-Host $_.Name " => " $fileName
# 變更檔案名稱
Rename-Item -Path $_.Name -NewName $fileName
}
這裡的檔案名稱規則是 yyyyMMdd-HHmmss,其中 yyyy 代表西元年、MM 代表月份、dd 代表日、HH 代表時、mm 代表分、ss 代表秒,這個檔案名稱結構可以自由調整。
實際執行的時候,會列出新舊檔案名稱的對照,如果找不到拍攝日期資訊的照片就會自動跳過:

自動編號
如果只想要使用日期來作為檔案名稱,可以將檔案名稱規則改為 yyyyMMdd,但是這樣就很容易出現重複的檔案名稱,最簡單的解決方式就是在日期之後加上自動遞增的編號,例如 20201031-01.jpg。
Get-ChildItem *.jpg | ForEach {
# 取得照片拍攝日期
$date = (.\exif-datetaken.ps1 $_.FullName)
# 檢查照片拍攝日期
if ($date -eq $null) {
Write-Host $_.Name ' 錯誤:找不到拍攝日期資訊。'
return
}
# 從 1 開始編號
$index = 1
do {
# 以日期與時間作為新檔案名稱
$fileName = $date.ToString('yyyyMMdd') + ('-{0:00}' -f $index++) + '.jpg'
} while (Test-Path -Path $fileName -PathType leaf)
# 顯示新舊檔案名稱
Write-Host $_.Name " => " $fileName
# 變更檔案名稱
Rename-Item -Path $_.Name -NewName $fileName
}
