shell-music-refactor-library/refactor_music_library.sh

221 lines
5.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# 2025 Hyperling
# Clean up a music library. Improved version of rename_music_files.sh.
# Steps:
# 0) Ensure an OLD folder exists, it is what will be refactored.
# 1) Convert all non-mp3 files to mp3 and put them in an INTERIM folder.
# 2) Loop over all OLD and INTERIM's mp3 files and move them to NEW based on data.
# - Name the file as "${ZERO_LED_TRACK_NUMBER}. ${SONG_TITLE}
# - Name parent folder as "${YEAR} - ${ALBUM}" if both exist, otherwise just one or the other "${YEAR}${ALBUM}".
# - Name grandparent folder as "${ARTIST} - ${GENRE}" if both exist, otherwise "${ARTIST}${GENRE}".
# TODO list:
# - Organize tracks by Artist + Album folders.
# - Name parent folder as "$YEAR - $ALBUM" if both exist, otherwise just one or the other.
# - Name grandparent folder as ARTIST if it exists, otherwise GENRE.
## Facts and Variables ##
DIR="`pwd`"
PROG="$(basename -- "${BASH_SOURCE[0]}")"
FAIL=".$PROG.exit-error"
OLD="$DIR/OLD"
NEW="$DIR/NEW"
INT="$DIR/INTERIM"
## Checks and Setup ##
# System Packages #
echo "* Checking if necessary tools are installed."
function needed_progs {
cat <<- EOF
ffmpeg
exiftool
EOF
}
needed_progs | while read prog; do
if [[ -z "`which $prog`" ]]; then
echo "ERROR: $prog not found, please install."
touch $FAIL
fi
done
if [[ -e $FAIL ]]; then
rm -fv $FAIL
exit 1
fi
echo "** Tools are available."
# Old Directory #
echo "* Checking whether OLD directory exists."
if [[ "`pwd`" == *"/OLD" ]]; then
echo "** We are in the folder, moving up a directory."
cd ..
fi
if [[ ! -d "OLD" ]]; then
echo "ERROR: Could not find a folder named 'OLD'."
echo " Please create it and add your library there."
fi
echo "** Folder exists appropriately."
# Other Directories #
echo "* Ensuring working directories NEW and INTERIM exist."
mkdir -pv "$NEW" "$INT"
## Convert Media ##
echo "* Convert all files to mp3."
find "$OLD" ! -name "*".mp3 | while read file; do
ffmpeg -nostdin -hide_banner -loglevel quiet -i "$file" "$file".converted.mp3
done
echo "** Done converting mp3s."
## Transform Media ##
function migrate_music {
file="$1"
command="$2"
if [[ -z $file ]]; then
echo "ERROR: No filename retrieved, cannot migrate."
return 1
fi
if [[ -z "$command" ]]; then
command="cp"
fi
echo "** $file **"
# Retrieve and clean the Title
title=""
title="`exiftool -Title "$file"`"
title="${title//Title /}"
title="${title// : /}"
title="${title//[^[:alnum:][:space:].]/}"
title="`echo $title`"
while [[ "$title" == *" "* ]]; do
title="${title// / }"
done
echo "*** Title=$title"
new_file="$title$EXT"
# Retrieve and clean the Track Number
track=""
# Get raw value
track="`exiftool -Track "$file"`"
# Filter the header
track="${track//Track /}"
track="${track// : /}"
# Remove disk designations
track="${track%%/*}"
# Remove any whitespace before/after
track="`echo $track`"
# Add a leading 0 to single digits.
[[ ${#track} == 1 ]] && track="0$track"
echo "*** Track=$track"
new_file="$track. $new_file"
# Add the Album and Year.
album=""
album="`exiftool -Album "$file"`"
album="${album//Album /}"
album="${album// : /}"
album="${album//[^[:alnum:][:space:].]/}"
album="`echo $album`"
while [[ "$album" == *" "* ]]; do
album="${album// / }"
done
echo "*** Album=$album"
year=""
year="`exiftool -Year "$file"`"
year="${year//Year /}"
year="${year// : /}"
year="${year//[^[:alnum:][:space:].]/}"
year="`echo $year`"
while [[ "$year" == *" "* ]]; do
year="${year// / }"
done
echo "*** Year=$year"
parent=""
if [[ -s $year && -s $album ]]; then
parent="$year - $album"
else
parent="$year$album"
fi
new_file="$parent/$new_file"
# Add the Artist.
artist=""
artist="`exiftool -Artist "$file"`"
artist="${artist//Artist /}"
artist="${artist// : /}"
artist="${artist//[^[:alnum:][:space:].]/}"
artist="`echo $artist`"
while [[ "$artist" == *" "* ]]; do
artist="${artist// / }"
done
echo "*** Artist=$artist"
band=""
band="`exiftool -Band "$file"`"
band="${band//Band /}"
band="${band// : /}"
band="${band//[^[:alnum:][:space:].]/}"
band="`echo $band`"
while [[ "$band" == *" "* ]]; do
band="${band// / }"
done
echo "*** Band=$band"
album_artist=""
album_artist="`exiftool -Albumartist "$file"`"
album_artist="${album_artist//Albumartist /}"
album_artist="${album_artist// : /}"
album_artist="${album_artist//[^[:alnum:][:space:].]/}"
album_artist="`echo $album_artist`"
while [[ "$album_artist" == *" "* ]]; do
album_artist="${album_artist// / }"
done
echo "*** Albumartist=$album_artist"
# Prefer Artist, then Band, then Albumartist
grandparent=""
if [[ -s $album ]]; then
grandparent="$album"
elif [[ -s $band ]]; then
grandparent="$band"
elif [[ -s $album_artist ]]; then
grandparent="$album_artist"
else
grandparent="Unknown"
fi
new_file="$grandparent/$new_file"
# Move the file.
new_file="$NEW/$new_file"
$command -v "$file" "$new_file"
echo "*** Finished file!"
}
echo "* Moving INTERIM files to NEW."
find "$INT" -name "*".mp3 | while read file; do
migrate_music "$file" mv
done
echo "** Done with INTERIM, deleting."
rm -rfv "$INT"
echo "* Copying OLD files to NEW."
find "$OLD" -name "*".mp3 | while read file; do
migrate_music "$file" cp
done