#!/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# 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. new_file="$parent/$new_file" # Add the Artist and Genre. new_file="$grandparent/$new_file" # Move the file. new_file="$NEW/$new_file" $command "$file" "$new_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