Mac OS X下基于两种匹配模式批量重命名文件的方法
批量重命名:提取季度标识并前置为标准格式(OSX Terminal/Ruby方案)
我明白你现在的需求——批量把文件名里的两种季度格式(XQXX比如3Q17,或者XXQX比如17Q3)转换成标准的20XXQX格式,然后加到文件名最前面用下划线分隔。你提到Ruby代码能正常运行,但brew安装的rename脚本返回错误结果,那我给你整理几个靠谱的方案:
方案1:优化后的Ruby批量处理脚本
既然你已经验证过Ruby可行,这里给一个更通用、安全的单行命令或脚本,适合批量处理目标文件夹里的文件:
单行命令(直接在目标文件夹执行)
Dir.glob("*.pdf").each do |file| if match = file.match(/(\d)Q(\d{2})/) new_prefix = "20#{match[2]}Q#{match[1]}" elsif match = file.match(/(\d{2})Q(\d)/) new_prefix = "20#{match[1]}Q#{match[2]}" end next unless new_prefix new_name = "#{new_prefix}_#{file}" File.rename(file, new_name) unless File.exist?(new_name) end
关键细节:
- 用
Dir.glob("*.pdf")匹配所有PDF文件,如果要处理所有类型文件,改成Dir.glob("*") - 先匹配
XQXX(比如3Q17)的模式,再匹配XXQX(比如17Q3)的模式,分别提取年份和季度 - 重命名前先检查新文件名是否存在,避免意外覆盖文件
- 如果文件名里没有匹配的季度格式,会自动跳过,不会修改
可执行脚本版本
把上面的代码保存为rename_quarters.rb,然后在Terminal里执行:
chmod +x rename_quarters.rb ./rename_quarters.rb
方案2:修正brew安装的perl-rename用法
你遇到brew版rename出错的问题,是因为brew安装的是perl-rename(和OSX系统默认的rename语法完全不同),之前的正则写法不对。下面是正确的命令:
第一步:确认安装perl-rename
如果还没装,先执行:
brew install rename
第二步:预览+执行重命名
先执行预览命令(不会实际修改文件,用来验证结果):
rename -n 's/^.*?(?:(\d)Q(\d{2})|(\d{2})Q(\d)).*?$/20${2:$3}Q${1:$4}_$&/' *.pdf
如果预览结果符合你的预期(比如你的示例文件能正确转换成2017Q3_XXX.pdf、2013Q2_XXX.pdf),去掉-n参数执行实际重命名:
rename 's/^.*?(?:(\d)Q(\d{2})|(\d{2})Q(\d)).*?$/20${2:$3}Q${1:$4}_$&/' *.pdf
正则解释:
(?:...)是非捕获组,用来分支匹配两种季度格式${2:$3}:如果匹配的是XQXX模式,$3为空,取$2(年份后两位);如果是XXQX模式,$2为空,取$3,自动适配两种格式${1:$4}同理,自动取正确的季度数字_$&保留原文件名,前面加下划线分隔
方案3:OSX原生工具组合(无需brew)
如果你不想依赖brew,也可以用OSX自带的find、sed、mv组合实现:
find . -maxdepth 1 -type f -name "*.pdf" | while read -r file; do prefix=$(echo "$file" | sed -E 's/.*?(\d)Q(\d{2}).*/20\2Q\1/;t;s/.*?(\d{2})Q(\d).*/20\1Q\2/') if [ "$prefix" != "$file" ]; then mv -n "$file" "${prefix}_${file}" fi done
细节说明:
find只查找当前目录下的PDF文件(-maxdepth 1避免递归子文件夹)sed先尝试匹配XQXX模式,替换成标准格式;如果匹配失败,再匹配XXQX模式mv -n避免覆盖已存在的文件,更安全
内容的提问来源于stack exchange,提问作者user2012677




