介紹如何在 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, 0, $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 }
參考資料:tabsoverspaces