我有一个名为的文件列表mp3
,如下所示:
$artist/$album ($year)/$tracknum $title.mp3
其中许多曲目的标签不正确或缺失,我正在通过使用id3v2
和正则表达式,因为文件名都是正确的。下面是我设置标题的示例:
for mp3 in *.mp3; do id3v2 -t "$(echo $mp3 | cut -d. -f1 | cut -d\ -f2-)" "$mp3"; done
(注意:之所以使用引号是因为标题中经常有空格,如果不使用空格,则会导致 bash 发出警告)
我的问题是:有没有更好的方法从这些文件中提取特定的子字符串?就标题而言,如果grep -o
不匹配,我就无法使用$tracknum
,因为许多曲目的标题中都有数字和空格(这意味着我需要"([0-9a-zA-Z ]+)"
我的模式,它匹配之前的整个文件名.mp3
)。
我几乎确信有更好的方法可以做到这一点。有吗?
答案1
如果您想要提取标题(并且,如果有用的话,还有曲目编号),您应该可以这样做:
read -r tracknum title <<<$(basename "$mp3" .mp3)
对于其他部分,我将首先拆分文件名以/
隔离各个部分。例如:
album_year=$(cut -d/ -f2 <<<"$mp3")
album=${album%\ (*)}
year=${album_year:-5:4}
最后一个取决于实际存在的年份和四位数字的长度;如果不能保证,那么您可以使用更笨拙的表达式来完成:
year=${album_year:$((${#album}+2)):$((${#album_year}-${#album}-3}
此外,如果您不知道该部分在路径中有多深album_year
,您可以使用以下命令提取倒数第二段(即文件的直接目录):
album_year=$(basename "$(dirname "$mp3")")
或者,你可以将整个路径拆分为一个数组:
IFS=/ read -ra segments <<<"$mp3"
album_year=${segments[-2]}