我的文件夹中有一堆 mp3 文件。它们是从盒式磁带录制的,并且需要将各个轨道分开。这是文件名之一:
Gobbolino the Witch's Cat, 10:52 The Hare & Tortoise, 14:52 The Shoe Tree, 24:22 The Emperors New Clothes, 34:11 The Red Nightcaps, 37:07 Aldo in Arcadia (1), 40:37 The Forest Troll.mp3
您可以看到它的文件名中有时间戳,指示每个曲目的开始。第一个曲目没有时间戳,因为它始终从 00:00 开始。最后一首曲目应始终位于 mp3 的末尾。不知何故,我想提取这些时间戳以便创建单独的文件。
如果上面的文件被正确分割,输出将是:
Gobbolino the Witch's Cat.mp3
The Hare & Tortoise.mp3
The Shoe Tree.mp3
The Emperors New Clothes.mp3
The Red Nightcaps.mp3
Aldo in Arcadia (1).mp3
The Forest Troll.mp3
我知道如何循环文件,以及如何使用 ffmpeg 剪切文件,但我不知道如何从文件名中提取时间戳和轨道名称。我正在使用 zsh,这是我当前的代码:
for file in *; do
if [[ -f "$file" ]]; then
# extract timestamps and loop thru, for each timestamped section
ffmpeg -ss TIMESTAMP_START -to TIMESTAMP_END -I "$file" -acodec copy TRACK_NAME.mp3
fi
done
更新
我对这个问题的规范已经改变。文件名如下所示:
Tape 1 - Gobbolino the Witch's Cat, 11-06 The Hare & Tortoise, 14-25 The Shoe Tree, 24-06 The Emperors New Clothes, 34-27 The Red Nightcaps, 37-29 Aldo in Arcadia (1), 40-40 The Forest Troll.mp3
即它的开头有一个专辑名称,时间戳中有连字符而不是冒号(macOS 中文件名不能有冒号)。另外,我想在文件中插入一些 mp3 标签,并将每个专辑的曲目放入其自己的专辑文件夹中。
我的解决方案基于下面的 Gilles 之一。该脚本如下所示:
setopt interactive_comments
for file in *(.); do
extension=$file:e
rest=$file:r
timestamp_start=0:00
timestamp_duration=$(ffprobe -i "$file" -show_entries format=duration -v quiet -of csv="p=0" -sexagesimal -sexagesimal)
timestamp_duration=${timestamp_duration%.*}
tracknum=1
while [[ $rest =~ ,\ *([0-9:]+-[0-9][0-9])\ * ]]; do
track_name="$rest[1,$MBEGIN-1]"
if [[ "$track_name" == *"Tape "* ]]; then
albumname="${track_name%% - *}"
track_name="${track_name#* - }"
echo "\n\nALBUM NAME $albumname\n"
mkdir $albumname
fi
rest=$rest[$MEND+1,-1]
timestamp_end=$match[1]
timestamp_end="${timestamp_end//-/:}"
# echo "$timestamp_start $timestamp_end $track_name.$extension"
ffmpeg -ss $timestamp_start -to $timestamp_end -i $file -acodec libmp3lame -ac 2 -ab 256k -ar 44100 -metadata album="$albumname" -metadata title="$track_name" -metadata track="$tracknum" $track_name.$extension
mv $track_name.$extension $albumname
timestamp_start=$timestamp_end
tracknum=$((tracknum+1))
last_track_name="$rest:r"
done
if [[ -n $timestamp_end ]]; then
# echo "$timestamp_start $timestamp_duration $last_track_name.$extension"
ffmpeg -ss $timestamp_start -to $timestamp_duration -i $file -acodec libmp3lame -ac 2 -ab 256k -ar 44100 -metadata album="$albumname" -metadata title="$last_track_name" -metadata track="$tracknum" $last_track_name.$extension
mv $last_track_name.$extension $albumname
fi
done
答案1
使用正则表达式对文件名进行循环来匹配轨道分隔符=~
条件表达式运算符。正则表达式,\ *([0-9:]+:[0-9][0-9])\ *
匹配一个逗号,后跟一个时间戳,周围有可选空格。
$file:e
并$file:r
通过提取文件扩展名历史修正。
不要循环遍历所有文件然后仅匹配常规文件,而是使用全局限定符仅匹配常规文件。
for file in *(.); do
extension=$file:e
rest=$file:r
timestamp_start=0:00
timestamp_end=
while [[ $rest =~ ,\ *([0-9:]+:[0-9][0-9])\ * ]]; do
track_name=$rest[1,$MBEGIN-1]
rest=$rest[$MEND+1,-1]
timestamp_end=$match[1]
ffmpeg -ss $timestamp_start -to $timestamp_end -I $file -acodec copy $track_name.$extension
timestamp_start=$timestamp_end
done
if [[ -n $timestamp_end ]]; then
ffmpeg -ss $timestamp_end -I $file -acodec copy $rest.$extension
else
: # If you want special processing for single-track files, it goes here.
fi
done
答案2
awk -F "," '{for(i=1;i<=NF;i++){gsub(/[0-9]{2}:[0-9]{2}/,"",$i);gsub(/^[[:space:]]*/,"",$i);print $i".mp3"}}' file.txt
输出
Gobbolino the Witch's Cat.mp3
The Hare & Tortoise.mp3
The Shoe Tree.mp3
The Emperors New Clothes.mp3
The Red Nightcaps.mp3
Aldo in Arcadia (1).mp3
The Forest Troll.mp3.mp3