#!/bin/bash TIMEOUT=10 function renameSong() { fullSongPath=$1 songFileBaseName=$(basename "${fullSongPath}") songFileExtension="${songFileBaseName##*.}" if [ "${songFileExtension}" == "mp3" ]; then if [ -f "${fullSongPath}" ]; then echo "Trying to recognize song: ${fullSongPath}" songRecOutput=$(timeout ${TIMEOUT} songrec recognize "${fullSongPath}" --csv) if [ $? -eq 0 ]; then songRecOutput=$(echo -e "${songRecOutput}" | tail -1) parsedMetaData=$(parseMetaData "${songRecOutput}") readarray -d "|" -t parsedMetaDataParts <<< "${parsedMetaData}" newSongPath="$(dirname "${fullSongPath}")/${parsedMetaDataParts[0]}/${parsedMetaDataParts[1]}" mkdir -p "${newSongPath}" songName=$(echo "${parsedMetaDataParts[2]}" | tr -d '\n') mv -f "${fullSongPath}" "${newSongPath}/${songName}.${songFileExtension}" else echo "Failed to recognize song within ${TIMEOUT} seconds. Skipping." fi else echo "Failed to find song: ${fullSongPath}" fi echo "-------------------------------------------------------" else echo "The following extension is not supported: ${songFileExtension}. Skipping." fi } function trim() { var="$*" var="${var#"${var%%[![:space:]]*}"}" var="${var%"${var##*[![:space:]]}"}" printf '%s' "${var}" } function fetchCsvPart() { text=$1 csvPartNr=$2 csvPart=$(echo "${text}" | awk -v idx="${csvPartNr}" 'BEGIN {FPAT = "([^,]*)|(\"[^\"]+\")"}{printf("%s", $idx)}') echo "${csvPart//\"/}" } function parseMetaData() { metaData=$1 albumName=$(fetchCsvPart "${metaData}" "2") artistAndSongName=$(fetchCsvPart "${metaData}" "1") readarray -d "-" -t artistAndSongNameParts <<< "${artistAndSongName}" artistName=$(trim "${artistAndSongNameParts[0]}") songName=$(trim "${artistAndSongNameParts[1]}") songName="${songName//[\/]/ _ }" if [ "${artistName}" == "" ]; then artistName="Unknown" fi if [ "${albumName}" == "" ]; then albumName="Unknown" fi echo "${artistName}|${albumName}|${songName}" } # Main IFS=$(echo -en "\n\b") if [ $# -gt 0 ]; then fsArg=$(realpath "$1") if [ -f "${fsArg}" ]; then renameSong "${fsArg}" elif [ -d "${fsArg}" ]; then songFilePaths=$(find "${fsArg}" -maxdepth 1 -mindepth 1 -type f -exec readlink -f {} \;) for songFilePath in ${songFilePaths}; do renameSong "${songFilePath}" done else echo "The provided argument does not seem to be a valid file or directory: ${fsArg}" fi else echo "Please provide either a song file name or a directory containing one or more song files." fi