使用eyeD3、find与xargs批量设置MP3标签的技术求助
批量修改有声书MP3的Title标签(基于eyeD3命令行)
需求背景
我的有声书文件命名格式为「001 bookname.mp3」,但当前所有MP3的title标签均为bookname,导致VLC播放器的播放列表里无法区分章节,续听非常不便。希望通过命令行批量完成两个目标之一:
- 将文件名(去掉扩展名)设置为title标签
- 提取MP3本身的track编号,设置为title标签
现有尝试的问题
- 单文件场景下,我可以用这条命令实现用track编号设置title:
eyeD3 001 bookname.mp3 | awk '/track/ {print $2}' | xargs -I% sh -c 'eyeD3 -t % "001 bookname.mp3"' - 但尝试批量处理时,执行
find . -iname "*.mp3" -exec eyeD3 -t "{}" {}出现错误:find: Only one instance of {} is supported with -exec ... +,而且这个命令会把.mp3扩展名也带入title标签。
解决方案
方案1:从文件名提取章节+书名设置Title
利用文件名的固定格式,提取不带扩展名的部分作为title:
find . -type f -iname "*.mp3" -exec sh -c ' for file do # 去掉文件扩展名,得到"001 bookname"格式的标题 title=$(basename "$file" .mp3) # 设置title标签 eyeD3 -t "$title" "$file" done ' sh {} +
优势
- 用
find批量传递文件,处理效率高 basename能准确移除.mp3扩展名,兼容文件名含其他点的情况- 全程用引号包裹变量,避免带空格的文件名出现错误
方案2:从MP3的Track编号提取并设置Title
如果MP3文件本身已经有正确的track编号,可批量提取并设置:
find . -type f -iname "*.mp3" -exec sh -c ' for file do # 提取track编号:过滤eyeD3输出中的track行,取第二个字段 track_num=$(eyeD3 "$file" | awk '/track/ {print $2}') # 仅当track编号存在时才设置标签 if [ -n "$track_num" ]; then eyeD3 -t "$track_num" "$file" else echo "警告:文件 $file 未找到track编号" fi done ' sh {} +
错误原因说明
之前的find命令报错,是因为-exec ... +会把所有匹配文件一次性传给命令,这种模式下{}只能出现一次。而你写的eyeD3 -t "{}" {}里{}出现了两次,违反了规则。用sh -c包裹循环后,就可以对每个文件多次引用变量,解决这个问题。
内容的提问来源于stack exchange,提问作者Dee
相关产品推荐
相关产品推荐

