如何通过Bash脚本利用目录名批量修正音频文件FFmpeg元数据
基于文件夹名称批量修正音频元数据(FFmpeg + Bash脚本)
问题分析
你的脚本存在几个关键问题导致无法正常工作:
- 变量赋值错误:
art= basename "${artist}"写法不符合Bash语法,获取命令输出给变量需要用命令替换,正确格式是art=$(basename "${artist}") - 曲目遍历范围错误:
for track in ./*/是遍历专辑文件夹下的子文件夹,而音频文件是普通文件,应该去掉末尾斜杠,写成./*(或指定具体音频扩展名如./*.mp3) - 目录切换后未回退:每次
cd进入子目录后没有返回上层目录,导致后续循环的路径完全混乱,建议直接用绝对路径处理,避免目录切换带来的问题
修正后的可用脚本
下面是能正常批量处理的脚本,会按你的目录结构遍历艺术家、专辑文件夹,对每个音频文件自动用文件夹名填充元数据:
#!/bin/bash # 指定音频库根目录 MUSIC_ROOT="/tank/music" # 遍历所有艺术家文件夹 for artist_dir in "${MUSIC_ROOT}"/*/; do # 提取艺术家名称(去掉路径和末尾斜杠) artist_name=$(basename "${artist_dir}") # 遍历当前艺术家下的所有专辑文件夹 for album_dir in "${artist_dir}"/*/; do # 提取专辑名称 album_name=$(basename "${album_dir}") # 遍历专辑文件夹下的所有音频文件(跳过子目录) for track_file in "${album_dir}"/*; do # 只处理普通文件,跳过目录 [ -f "${track_file}" ] || continue # 创建临时文件,避免直接覆盖原文件导致损坏 temp_file="${track_file}.tmp" # 执行FFmpeg元数据修正,用流复制避免重新编码 ffmpeg -i "${track_file}" \ -metadata artist="${artist_name}" \ -metadata album="${album_name}" \ -c:v copy -c:a copy \ "${temp_file}" # 检查FFmpeg执行状态,成功则替换原文件,失败则删除临时文件 if [ $? -eq 0 ]; then mv "${temp_file}" "${track_file}" echo "已修正:${track_file}" else rm -f "${temp_file}" echo "修正失败:${track_file}" fi done done done
关键细节说明
-c:v copy -c:a copy:启用流复制模式,不会重新编码音频/视频,处理速度极快且完全不损失音质- 临时文件机制:先输出到临时文件,确认处理成功后再替换原文件,避免意外损坏原音频
- 扩展名适配:如果你的音频只有特定格式(如mp3、flac),可以把
"${album_dir}"/*改成"${album_dir}"/*.mp3 "${album_dir}"/*.flac,减少无效遍历 - 绝对路径处理:全程使用绝对路径,彻底避免目录切换带来的路径混乱问题
使用注意事项
- 先挑选少量音频文件测试脚本,确认元数据修正符合预期后再批量处理
- 确保系统已安装FFmpeg:Debian/Ubuntu可执行
sudo apt install ffmpeg,RHEL/CentOS可执行sudo dnf install ffmpeg
内容的提问来源于stack exchange,提问作者Asem Khen




