如何按照片实际拍摄日期批量重命名文件夹中的JPG图片?
解决方法:获取照片EXIF拍摄日期来重命名
你的问题在于$_.CreationDate调用的是文件系统的创建时间(也就是文件被复制到当前文件夹的时间),而我们需要的是照片本身的EXIF拍摄日期——也就是Windows资源管理器「日期」列显示的数值(这个值优先读取照片的拍摄时间,没有的话才会 fallback 到文件时间)。
下面是两种可行的原生PowerShell实现方法,不需要额外安装工具:
方法1:利用Windows Shell属性读取拍摄日期
Windows资源管理器显示的「日期」其实对应Shell属性里的System.Photo.DateTaken,我们可以通过Shell.Application来获取这个属性值:
$shell = New-Object -ComObject Shell.Application Get-ChildItem -Path "./" -Recurse -Include "*.jpg" | ForEach-Object { $folder = $shell.Namespace($_.DirectoryName) $file = $folder.ParseName($_.Name) # 获取拍摄日期属性(属性ID 12对应System.Photo.DateTaken) $dateTaken = $folder.GetDetailsOf($file, 12) if ($dateTaken) { # 将意大利语格式的日期转换为DateTime对象,再格式化为yyyyMMddHHmmss # 意大利语日期格式通常是dd/MM/yyyy HH:mm:ss,所以指定文化信息解析 $dateObj = [DateTime]::Parse($dateTaken, [System.Globalization.CultureInfo]::GetCultureInfo("it-IT")) $newName = $dateObj.ToString("yyyyMMddHHmmss") + "_" + $_.Name.Replace("IMG", "") # 避免重名,添加序号 $counter = 1 $finalName = $newName while (Test-Path (Join-Path $_.DirectoryName $finalName)) { $finalName = $dateObj.ToString("yyyyMMddHHmmss") + "_$counter_" + $_.Name.Replace("IMG", "") $counter++ } Rename-Item -Path $_.FullName -NewName $finalName -Force } else { # 如果没有拍摄日期, fallback 到文件创建时间 $newName = $_.CreationDate.ToString("yyyyMMddHHmmss") + "_" + $_.Name.Replace("IMG", "") Rename-Item -Path $_.FullName -NewName $newName -Force Write-Warning "没有找到照片 $($_.Name) 的拍摄日期,使用文件创建日期重命名" } }
代码说明:
- 用
Shell.Application获取文件夹和文件对象,通过属性ID 12获取拍摄日期(这个ID在Windows中是固定对应Date Taken的) - 因为你用的是意大利语Windows,所以解析日期时指定
it-IT文化信息,确保能正确识别dd/MM/yyyy格式的日期 - 添加了重名处理逻辑,避免同名文件覆盖
- 如果照片没有EXIF拍摄日期,会自动 fallback 到原来的文件创建时间
方法2:直接读取EXIF元数据(需要PowerShell 5.1及以上)
另一种方法是直接读取图片的EXIF属性DateTimeOriginal,这是照片拍摄时相机记录的原始时间:
Get-ChildItem -Path "./" -Recurse -Include "*.jpg" | ForEach-Object { try { # 读取图片的EXIF元数据 $image = [System.Drawing.Image]::FromFile($_.FullName) $dateTakenProp = $image.GetPropertyItem(36867) # 36867是DateTimeOriginal的EXIF标签ID $dateTakenStr = [System.Text.Encoding]::ASCII.GetString($dateTakenProp.Value).TrimEnd([char]0) # 将EXIF的日期格式(yyyy:MM:dd HH:mm:ss)转换为DateTime对象 $dateObj = [DateTime]::ParseExact($dateTakenStr, "yyyy:MM:dd HH:mm:ss", $null) $newName = $dateObj.ToString("yyyyMMddHHmmss") + "_" + $_.Name.Replace("IMG", "") # 重名处理 $counter = 1 $finalName = $newName while (Test-Path (Join-Path $_.DirectoryName $finalName)) { $finalName = $dateObj.ToString("yyyyMMddHHmmss") + "_$counter_" + $_.Name.Replace("IMG", "") $counter++ } Rename-Item -Path $_.FullName -NewName $finalName -Force $image.Dispose() } catch { # 读取EXIF失败时,使用文件创建时间 $newName = $_.CreationDate.ToString("yyyyMMddHHmmss") + "_" + $_.Name.Replace("IMG", "") Rename-Item -Path $_.FullName -NewName $newName -Force Write-Warning "无法读取照片 $($_.Name) 的EXIF数据:$_,使用文件创建日期重命名" } }
代码说明:
- 直接通过
System.Drawing.Image读取EXIF标签DateTimeOriginal(标签ID 36867) - 解析EXIF中固定格式的日期字符串
yyyy:MM:dd HH:mm:ss,不需要考虑系统语言 - 同样包含重名处理和 fallback 逻辑
注意事项:
- 运行方法2时,可能需要以管理员权限启动PowerShell,避免权限不足无法读取图片文件
- 对于经过编辑或无EXIF数据的照片,两种方法都会自动使用文件创建时间作为备选
- 如果你想保留原文件名的部分内容,可以调整
$newName的拼接逻辑,比如把$_.Name.Replace("IMG", "")改成你需要的格式
内容的提问来源于stack exchange,提问作者s_federici




