#!/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