批量重命名MP3文件的Bash脚本需求及正则问题排查
解决MP3批量按元数据重命名的正则失效问题
完整可运行的rename-mp3函数
把这段代码放到你的~/.bashrc或~/.zshrc中,重载终端后就能用rename-mp3 目标文件夹触发批量重命名:
rename-mp3() { local target_dir="${1:-.}" # 遍历目标目录及子目录下的所有MP3文件 find "$target_dir" -type f -iname "*.mp3" | while read -r mp3_file; do # 用ffprobe提取ID3元数据(兼容特殊字符,需先装ffmpeg) artist=$(ffprobe -v error -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$mp3_file") title=$(ffprobe -v error -show_entries format_tags=title -of default=noprint_wrappers=1:nokey=1 "$mp3_file") # 跳过无有效元数据的文件 [[ -z "$artist" || -z "$title" ]] && echo "跳过无元数据文件: $mp3_file" && continue # 关键字符清理(替换你之前失效的#?正则逻辑) cleaned_artist=$(echo "$artist" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-|-$//g') cleaned_title=$(echo "$title" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-|-$//g') # 生成标准格式文件名 new_filename="${cleaned_artist}_${cleaned_title}.mp3" new_filepath=$(dirname "$mp3_file")/"$new_filename" # 处理文件名重复情况 local count=1 while [[ -f "$new_filepath" ]]; do new_filepath=$(dirname "$mp3_file")/"${cleaned_artist}_${cleaned_title}_$count.mp3" ((count++)) done # 执行重命名(可先替换成echo预览效果) mv -v "$mp3_file" "$new_filepath" done }
正则失效的核心修正点
- 启用扩展正则模式:用
sed -E替代基础正则,确保[^a-z0-9]+这类匹配逻辑生效——它会把所有非字母数字的字符(空格、特殊符号、乱码)统一替换为连字符;s/^-|-$//g负责清理首尾多余的连字符。 - 统一字符大小写:通过
tr '[:upper:]' '[:lower:]'强制转小写,保证文件名格式一致性。 - 兼容特殊字符:依赖
ffprobe提取元数据,比传统id3工具更好支持ü、ț这类非ASCII字符,需先安装ffmpeg包(sudo apt install ffmpeg或brew install ffmpeg)。
测试验证
拿你给出的示例文件s3 24)3ü6 Dț67 .mp3测试:如果元数据是艺术家Goran Bregovic、标题Underground Cocek,最终会被重命名为goran-bregovic_underground-cocek.mp3,完全符合要求。
注意事项
- 重命名前可将
mv -v替换为echo "将重命名: $mp3_file -> $new_filepath",先预览效果再执行实际操作。 - 若遇到元数据编码乱码,可在
ffprobe命令中添加-charset utf8强制指定编码。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

