Rename photos by date
Turns IMG_4821.jpg into 2026-09-24_14-05-33.jpg, using the date the camera recorded. Photos from different phones then sort in the order they were taken. It shows you the new names first and never overwrites a file.
1. Save the script
Save this as rename-photos.ps1 in your Scripts folder (for example C:\Users\Thandi\Scripts).
rename-photos.ps1
<#
Rename photos and videos in a folder to the date they were taken, for example
2026-09-24_14-05-33.jpg, so they sort in order. JPG files use the date stored by
the camera; other files use the date they were last changed. It only shows what
it would do unless you add -Apply, and it never overwrites a file.
powershell -ExecutionPolicy Bypass -File .\rename-photos.ps1 -Folder "C:\Users\You\Pictures\Holiday"
powershell -ExecutionPolicy Bypass -File .\rename-photos.ps1 -Folder "C:\Users\You\Pictures\Holiday" -Apply
Free from Voypelo Solutions, voypelo.co.za. MIT licence.
#>
param(
[Parameter(Mandatory = $true)][string]$Folder,
[switch]$Apply
)
Add-Type -AssemblyName System.Drawing
$extensions = @('.jpg', '.jpeg', '.png', '.heic', '.mp4', '.mov')
function Get-TakenDate($file) {
if ($file.Extension -match '^\.(jpe?g)$') {
try {
$img = [System.Drawing.Image]::FromFile($file.FullName)
try {
# 36867 is the EXIF "date taken" tag written by cameras and phones.
if ($img.PropertyIdList -contains 36867) {
$raw = [System.Text.Encoding]::ASCII.GetString($img.GetPropertyItem(36867).Value).Trim([char]0)
return [datetime]::ParseExact($raw, 'yyyy:MM:dd HH:mm:ss', $null)
}
} finally {
$img.Dispose()
}
} catch {
# Unreadable or unusual file: fall back to the file date below.
}
}
return $file.LastWriteTime
}
if (-not (Test-Path -LiteralPath $Folder -PathType Container)) {
Write-Error "Expected a folder at $Folder, found nothing there"
exit 1
}
$count = 0
Get-ChildItem -LiteralPath $Folder -File |
Where-Object { $extensions -contains $_.Extension.ToLower() } |
ForEach-Object {
$stamp = (Get-TakenDate $_).ToString('yyyy-MM-dd_HH-mm-ss')
$ext = $_.Extension.ToLower()
if ($_.BaseName -eq $stamp -or $_.BaseName -like "${stamp}_*") { return } # already named
$newName = $stamp + $ext
$n = 2
while (Test-Path -LiteralPath (Join-Path $Folder $newName)) {
$newName = '{0}_{1}{2}' -f $stamp, $n, $ext
$n++
}
if ($Apply) {
Rename-Item -LiteralPath $_.FullName -NewName $newName
Write-Output ('renamed {0} -> {1}' -f $_.Name, $newName)
} else {
Write-Output ('would rename {0} -> {1}' -f $_.Name, $newName)
}
$count++
}
if ($Apply) {
Write-Output ('{0} file(s) renamed.' -f $count)
} else {
Write-Output ('{0} file(s) would be renamed. Run again with -Apply to rename them.' -f $count)
}2. Preview, then rename
In Command Prompt, point it at a folder of photos. First it only shows the new names:
powershell -ExecutionPolicy Bypass -File "%USERPROFILE%\Scripts\rename-photos.ps1" -Folder "%USERPROFILE%\Pictures\Holiday"If they look right, add -Apply:
powershell -ExecutionPolicy Bypass -File "%USERPROFILE%\Scripts\rename-photos.ps1" -Folder "%USERPROFILE%\Pictures\Holiday" -ApplyRunning it again on the same folder changes nothing, so it is safe to repeat.
Why it helps
Photos from a trip, a wedding or a site visit from three different phones finally line up in order.