How about ffmpeg
?
Well, ffprobe actually, but it's part of the package.
#!/bin/bash
set -o noclobber # just a precaution
get_metadata() {
local song="$1"
local song_track=$(ffprobe -v error -of csv=p=0 -show_entries format_tags=track "$song" | awk '{print $1}')
local song_title=$(ffprobe -v error -of csv=p=0 -show_entries format_tags=title "$song")
song_track=$(echo "$song_track" | awk '{printf "%02d\n", $0}') # pad track number to ensure it's two digits
echo "$song_track" "$song_title"
}
# list mp3s with their full paths
find "$(pwd)" -type f -name "*.mp3" > /tmp/my_mp3_list
readarray -t list_mp3s < /tmp/my_mp3_list
for song in "${list_mp3s[@]}"; do
IFS=' ' read -r song_track song_title <<< "$(get_metadata "$song")"
file_name="${song_track}-${song_title}.mp3"
file_name=$(echo "$file_name" | sed 's/[\/:*?"<>|]/_/g') # sanitize bad characters
dir_name=$(dirname "$song")
new_file_path="$dir_name/$file_name"
mv -- "$song" "$new_file_path"
echo "Renamed '$(basename -s .mp3 "$song").mp3' to '$(basename -s .mp3 "$new_file_path").mp3'"
done
rm tmp/my_mp3_list
exit 0
Save as: rename_from_id3.sh
Change mode executable: chmod +x rename_from_id3.sh
Usage: ./rename_from_id3.sh
Run from the .mp3
directory. All files in that directory will be renamed, recursively.