diff --git a/music-sync.sh b/music-sync.sh index 4608ae6..67f1ab9 100755 --- a/music-sync.sh +++ b/music-sync.sh @@ -8,14 +8,17 @@ #/ Syncronises music from one folder to another. #/ #/ Options: -#/ -s, --source The source folder of the music -#/ -d, --dest The destination folder of the music -#/ -t, --temp The temporary cache for converted files (default: /tmp/converted) -#/ -c, --convert Convert files to a given bitrate in kbps before syncing (default: 192) -#/ -a, --resize-art Resize album-art before syncing (default width: 200) -#/ -j, --jobs Number of processes to use in multi-threading (default: nproc - 2) -#/ -v, --verbose <0-6> Set log level (default: 2) +#/ -s, --source= The source folder of the music +#/ -d, --dest= The destination folder of the music +#/ -t, --temp= The temporary cache for converted files (default: /tmp/converted) +#/ -c, --convert= Convert files to a given bitrate in kbps before syncing (default: 192) +#/ -a, --resize-art= Resize album-art before syncing (default width: 200) +#/ -j, --jobs= Number of processes to use in multi-threading (default: nproc - 2) +#/ -v, --verbose=<0-6> Set log level (default: 2) #/ -h, --help Display this help text +#/ -p, --playlists Enable playlist sync +#/ -m, --mapping=DIR1,DIR2 Add mappings for playlists from DIR1 to DIR2 +#/ -w, --windows-format Use crlf and backslashes for playlists #/ #/ Log levels: #/ 0 | Verbose @@ -50,6 +53,10 @@ jobcount=$(expr $(nproc) - 2) multithread=false script_name=$(basename "${0}") script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +listmapping[0]='' +listmapping[1]='' +windowspaths=false +playlists=false CheckDeps() { if [[ $1 == 2 ]]; then @@ -110,12 +117,27 @@ CheckDeps() { if [[ ! $(parallel -h 2>/dev/null) ]]; then VerboseOutput 5 "\`parallel -h\` failed" VerboseOutput 5 "Sorry, It seems that parallel is not installed on your system" - VerboseOutput 5 "Please install gnu-parallel and env_parallel from your repositories and make sure it is available in your \$PATH" + VerboseOutput 5 "Please install gnu-parallel from your repositories and make sure it is available in your \$PATH" VerboseOutput 5 "Otherwise disable multithreading" ExecTime exit 1 fi - VerboseOutput 0 "\`parallel -h \` succeeded" + VerboseOutput 0 "\`parallel -h\` succeeded" + fi + + # Check playlist requirement + if [[ $playlists == true ]]; then + if [[ $windowspaths == true ]]; then + if [[ ! $(unix2dos --version 2>/dev/null) ]]; then + VerboseOutput 5 "\`unix2dos --version\` failed" + VerboseOutput 5 "Sorry, It seems that unix2dos is not installed on your system" + VerboseOutput 5 "Please install unix2dos from your repositories and make sure it is available in your \$PATH" + VerboseOutput 5 "Otherwise disable windows-format playlists" + ExecTime + exit 1 + fi + fi + VerboseOutput 0 "\`unix2dos --version\` succeeded" fi fi VerboseOutput 1 "Dependency test OK" @@ -124,8 +146,8 @@ CheckDeps() { GetOptions() { # https://stackoverflow.com/a/29754866 - OPTIONS=s:d:t:c::a::v::hj:: - LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help,jobs:: + OPTIONS=s:d:t:c::a::v::hj::pwm: + LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help,jobs::,playlists,windows-format,mapping: # -use ! and PIPESTATUS to get exit code with errexit set # -temporarily store output to be able to check for errors @@ -200,6 +222,26 @@ GetOptions() { shift 2 VerboseOutput 1 "Multithreading will use ${jobcount} threads" ;; + -p|--playlists) + VerboseOutput 0 "--playlists given" + playlists=true + shift + VerboseOutput 1 "Playlist sync enabled" + ;; + -w|--windows-format) + VerboseOutput 0 "--windows given" + windowspaths=true + shift + VerboseOutput 1 "Windows format playlists enabled" + ;; + -m|--mapping) + VerboseOutput 0 "--mapping given" + listmappingparam=(${2//,/ }) + listmapping[0]=${listmappingparam[0]:-""} + listmapping[1]=${listmappingparam[1]:-""} + shift 2 + VerboseOutput 1 "Playlist mappings enabled source=${listmapping[0]} dest=${listmapping[1]}" + ;; --) shift break @@ -276,22 +318,22 @@ CreateFileList() { origfile="${file#"$1/"}" relfile=$(echo ${origfile} | sed -e 's/\(\.\)*$//g' | tr -s ' ') mp3file=$(echo "${relfile}" | sed -e 's/.flac/.mp3/') - VerboseOutput 0 "Checking ${origfile}" + VerboseOutput 0 "Checking ${3}${origfile}" if [[ -d "${1}/$origfile" ]]; then VerboseOutput 0 "${origfile} is folder" - newdir="${3}/$origfile" + newdir="${3}$origfile" newdir=${newdir#"/"} VerboseOutput 1 "Entering $newdir" - CreateFileList "${1}/$origfile" "${2}/$relfile" "$newdir" + CreateFileList "${1}/$origfile/" "${2}/$relfile/" "$newdir/" elif [[ "${1}/$origfile" != *".m3u" ]] && [[ "${1}/$origfile" -nt "${2}/$mp3file" ]]; then - echo ${3}/$origfile >> /tmp/music-sync-filelist + echo ${3}$origfile >> /tmp/music-sync-filelist VerboseOutput 0 "${origfile} is newer in source" - VerboseOutput 2 "Added: ${3}/${origfile}" + VerboseOutput 2 "Added: ${3}${origfile}" + elif [[ $playlists == true ]] && [[ "${1}/$origfile" == *".m3u" ]]; then + echo ${3}$origfile >> /tmp/music-sync-filelist + VerboseOutput 0 "${origfile} is newer in source" + VerboseOutput 2 "Added playlist: ${3}${origfile}" fi - if [[ "${1}/$origfile" == *".m3u" ]]; then - VerboseOutput 0 "${origfile} is playlist" - fi - done } @@ -319,12 +361,6 @@ Execute() { else for line in $(cat "/tmp/music-sync-filelist") do - curline=$(expr ${curline} + 1) - total=$(cat /tmp/music-sync-filelist | wc -l) - percentage=$(echo "scale=4;${curline}/${total}" | bc) - percentage=$(echo "scale=2;${percentage}*100" | bc) - VerboseOutput 2 "Current file: $line" - VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%)" ProcessFile $line done fi @@ -339,11 +375,51 @@ ProcessFile() { VerboseOutput 2 "Current File: $line" VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%)" if [[ $convert == true ]]; then - ConvertFile "$line" + if [[ $line == *".m3u" ]]; then + ConvertPlaylist "$line" + else + ConvertFile "$line" + fi fi CopyFile "$line" } +ConvertPlaylist() { + line=${1} + if [[ ! -f "${source}/$line" ]]; then + VerboseOutput 5 "Source-file ${source}/$line Unreachable" + ExecTime + exit 3 + fi + + if [[ ! -d $(dirname "$temp/$line") ]]; then + VerboseOutput 0 "Creating folder $temp/${line%/*}" + mkdir -p "$temp/${line%/*}"; + fi; + + if [[ -f "$temp/$line" ]]; then + rm $temp/$line + fi + search=${listmapping[0]} + replace=${listmapping[1]} + VerboseOutput 0 "Creating playlist $temp/$line" + for item in $(cat "$source/$line") + do + mp3item=$(echo $item | sed -e 's/\.*\//\//g'| tr -s ' ') + if [[ $windowspaths == true ]]; then + echo "${mp3item/$search/$replace}" | sed -e 's,\/,\\,g' >> $temp/$line + else + echo "${mp3item/$search/$replace}" >> $temp/$line + fi + done + if [[ $windowspaths == true ]]; then + VerboseOutput 0 "Converting lf to crlf" + unix2dos $temp/$line 1>/dev/null 2>/dev/null + fi + VerboseOutput 1 "Converted: $line" + +} + ConvertFile() { line=${1} if [[ ! -f "${source}/$line" ]]; then @@ -352,12 +428,12 @@ ConvertFile() { exit 3 fi - if [[ "$temp/$line" = */* ]]; then + if [[ ! -d $(dirname "$temp/$line") ]]; then VerboseOutput 0 "Creating folder $temp/${line%/*}" mkdir -p "$temp/${line%/*}"; fi; mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/') - if [[ ! -f "$temp/$mp3line" || "${source}/$mp3line" -nt "$temp/$mp3line" ]]; then + if [[ "${source}/$line" -nt "$temp/$mp3line" ]]; then if [[ $line != *".mp3" ]]; then VerboseOutput 3 "${line} will be converted to mp3-file ${mp3line}" fi @@ -409,7 +485,7 @@ CopyFile() { destline=$(echo $mp3line | sed -e 's/\.*\//\//g'| tr -s ' ') VerboseOutput 1 "Copying: $line" - if [[ "$dest/$line" = */* ]]; then + if [[ ! -d $(dirname "$dest/$line") ]]; then VerboseOutput 0 "Creating folder $dest/${line%/*}" mkdir -p "$dest/${destline%/*}"; fi;