使用正则表达式批量重命名文件并保留关联文件名规则
批量重命名照片:保留原片与编辑版关联,按文件夹独立编号
场景与需求
已通过Exif Sorter将照片整理为%UserProfile%\Photos\%year%\%month%\%day%的层级文件夹结构,每个日期文件夹内的照片文件名格式杂乱,示例如下:
IMG_0001.jpg ZMGM00002.jpg ZMGM00003 (Edited).jpg ZMGM00003.jpg IMG_0002 (Edited).jpg IMG_0002.jpg IMG_0004.jpg
需要实现:
- 统一重命名为
DSC_XXXX.jpg格式,原片与对应编辑版共享同一编号(如DSC_0002.jpg和DSC_0002 (Edited).jpg) - 每个日期文件夹内的编号独立从1开始重新计数
- 支持批量处理近8万张照片,遍历上千个文件夹
当前使用RegexRenamer的问题:用正则^(\D+)(_)?(\d+)(Edited)?替换为DCS_$#$4会导致所有文件连续编号,丢失原片与编辑版的关联,结果不符合需求:
DSC_0001.jpg DSC_0002.jpg DSC_0003 (Edited).jpg DSC_0004.jpg DSC_0005 (Edited).jpg DSC_0006.jpg DSC_0007.jpg
解决方案
Windows 方案:PowerShell 脚本(原生支持,推荐)
PowerShell可遍历所有日期文件夹,按文件夹分组处理,自动识别原片与对应编辑版,再统一分配编号。
脚本代码
# 替换为你的照片库根路径 $rootPath = "$env:UserProfile\Photos" # 遍历所有年/月/日层级的文件夹 Get-ChildItem -Path $rootPath -Directory -Recurse | ForEach-Object { $folder = $_.FullName Write-Host "处理文件夹: $folder" # 获取当前文件夹内的照片文件(可扩展后缀如.png/.raw等) $photos = Get-ChildItem -Path $folder -File -Include "*.jpg", "*.jpeg" | Sort-Object Name # 分组:提取文件核心编号,将原片和编辑版归为同一组 $groups = $photos | Group-Object -Property { $name = $_.BaseName # 移除(Edited)后缀 $coreName = $name -replace "\s*\(Edited\)$", "" # 提取数字编号(兼容带/不带下划线的文件名) if ($coreName -match "\d+") { $matches[0] } else { $coreName } } # 为每组分配统一编号,执行重命名 $counter = 1 foreach ($group in $groups) { $padNumber = $counter.ToString("0000") foreach ($file in $group.Group) { $isEdited = $file.BaseName -match "\s*\(Edited\)$" $newBaseName = if ($isEdited) { "DSC_$padNumber (Edited)" } else { "DSC_$padNumber" } $newPath = Join-Path -Path $folder -ChildPath "$newBaseName$($file.Extension)" # 测试阶段可注释下面一行,用Write-Host $newPath预览结果 Rename-Item -Path $file.FullName -Destination $newPath -Force } $counter++ } }
使用说明
- 打开PowerShell,修改
$rootPath为你的照片库根目录 - 先注释
Rename-Item行,运行脚本预览重命名结果,确认无误后再取消注释执行实际重命名 - 脚本会自动遍历所有日期文件夹,每个文件夹内编号从1开始,原片与编辑版共享编号
Windows 方案:改进RegexRenamer逻辑(适合小批量)
若坚持使用RegexRenamer,需分三步处理:
- 标记关联组:
- 匹配带
(Edited)的文件:用正则^(.*?)(\d+)(.*)\(Edited\)(.*)$,替换为$2_TEMP_EDITED$4 - 匹配原片文件:用正则
^(.*?)(\d+)(.*)$,替换为$2_TEMP_ORIG$3
- 匹配带
- 按标记分组编号:按文件名前缀的数字分组,给每组分配
DSC_XXXX编号 - 恢复后缀:将
_TEMP_EDITED替换回(Edited),删除_TEMP_ORIG标记
macOS 方案:Shell 脚本
通过bash/zsh脚本实现遍历与分组编号,逻辑与PowerShell一致:
脚本代码
#!/bin/bash # 替换为你的照片库根路径 ROOT_PATH="$HOME/Photos" # 遍历所有日期文件夹 find "$ROOT_PATH" -type d | while read -r folder; do echo "处理文件夹: $folder" cd "$folder" || continue # 分组:将原片与编辑版按核心编号归类 declare -A file_groups for file in *.jpg *.jpeg; do if [[ -f "$file" ]]; then base=$(basename "$file" .${file##*.}) # 移除(Edited)后缀 core_base=${base%% *(Edited)} # 提取数字编号 if [[ "$core_base" =~ ([0-9]+) ]]; then core_num=${BASH_REMATCH[1]} else core_num="$core_base" fi file_groups["$core_num"]+="$file " fi done # 为每组分配编号并执行重命名 counter=1 for core_num in "${!file_groups[@]}"; do pad_num=$(printf "%04d" "$counter") files=${file_groups["$core_num"]} for file in $files; do base=$(basename "$file" .${file##*.}) if [[ "$base" == *"(Edited)" ]]; then new_name="DSC_${pad_num} (Edited).${file##*.}" else new_name="DSC_${pad_num}.${file##*.}" fi # 测试阶段可注释下面一行,用echo "重命名 $file -> $new_name"预览 mv -v "$file" "$new_name" done ((counter++)) done done
使用说明
- 打开终端,创建
rename_photos.sh文件并粘贴代码,修改ROOT_PATH - 赋予执行权限:
chmod +x rename_photos.sh - 先注释
mv -v行预览结果,确认无误后执行实际重命名
内容的提问来源于stack exchange,提问作者bananakid
相关产品推荐
相关产品推荐

