Regular-Expression
從文件名中提取時間戳以拆分 mp3
我在一個文件夾中有一堆 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
在文件名上使用循環來匹配軌道分隔符,使用正則表達式匹配
=~
條件表達式運算符。正則表達式,\ *([0-9:]+:[0-9][0-9])\ *
匹配一個逗號,後跟一個帶有可選空格的時間戳。
$file:e
並通過歷史修飾符$file:r
提取文件副檔名。不要循環遍歷所有文件然後只匹配正常文件,而是使用glob 限定符來匹配正常文件。
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