Compare commits
No commits in common. "main" and "develop" have entirely different histories.
162
music-sync.sh
162
music-sync.sh
@ -8,17 +8,14 @@
|
|||||||
#/ Syncronises music from one folder to another.
|
#/ Syncronises music from one folder to another.
|
||||||
#/
|
#/
|
||||||
#/ Options:
|
#/ Options:
|
||||||
#/ -s, --source=<source> The source folder of the music
|
#/ -s, --source <source> The source folder of the music
|
||||||
#/ -d, --dest=<destination> The destination folder of the music
|
#/ -d, --dest <destination> The destination folder of the music
|
||||||
#/ -t, --temp=<folder> The temporary cache for converted files (default: /tmp/converted)
|
#/ -t, --temp <folder> The temporary cache for converted files (default: /tmp/converted)
|
||||||
#/ -c, --convert=<bitrate> Convert files to a given bitrate in kbps before syncing (default: 192)
|
#/ -c, --convert <bitrate> Convert files to a given bitrate in kbps before syncing (default: 192)
|
||||||
#/ -a, --resize-art=<width> Resize album-art before syncing (default width: 200)
|
#/ -a, --resize-art <width> Resize album-art before syncing (default width: 200)
|
||||||
#/ -j, --jobs=<nproc> Number of processes to use in multi-threading (default: nproc - 2)
|
#/ -j, --jobs <nproc> Number of processes to use in multi-threading (default: nproc - 2)
|
||||||
#/ -v, --verbose=<0-6> Set log level (default: 2)
|
#/ -v, --verbose <0-6> Set log level (default: 2)
|
||||||
#/ -h, --help Display this help text
|
#/ -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:
|
#/ Log levels:
|
||||||
#/ 0 | Verbose
|
#/ 0 | Verbose
|
||||||
@ -53,10 +50,6 @@ jobcount=$(expr $(nproc) - 2)
|
|||||||
multithread=false
|
multithread=false
|
||||||
script_name=$(basename "${0}")
|
script_name=$(basename "${0}")
|
||||||
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
script_dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
mappingdest=''
|
|
||||||
mappingsrc=''
|
|
||||||
windowspaths=false
|
|
||||||
playlists=false
|
|
||||||
|
|
||||||
CheckDeps() {
|
CheckDeps() {
|
||||||
if [[ $1 == 2 ]]; then
|
if [[ $1 == 2 ]]; then
|
||||||
@ -117,27 +110,12 @@ CheckDeps() {
|
|||||||
if [[ ! $(parallel -h 2>/dev/null) ]]; then
|
if [[ ! $(parallel -h 2>/dev/null) ]]; then
|
||||||
VerboseOutput 5 "\`parallel -h\` failed"
|
VerboseOutput 5 "\`parallel -h\` failed"
|
||||||
VerboseOutput 5 "Sorry, It seems that parallel is not installed on your system"
|
VerboseOutput 5 "Sorry, It seems that parallel is not installed on your system"
|
||||||
VerboseOutput 5 "Please install gnu-parallel from your repositories and make sure it is available in your \$PATH"
|
VerboseOutput 5 "Please install gnu-parallel and env_parallel from your repositories and make sure it is available in your \$PATH"
|
||||||
VerboseOutput 5 "Otherwise disable multithreading"
|
VerboseOutput 5 "Otherwise disable multithreading"
|
||||||
ExecTime
|
ExecTime
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
||||||
fi
|
fi
|
||||||
VerboseOutput 1 "Dependency test OK"
|
VerboseOutput 1 "Dependency test OK"
|
||||||
@ -146,8 +124,8 @@ CheckDeps() {
|
|||||||
GetOptions() {
|
GetOptions() {
|
||||||
|
|
||||||
# https://stackoverflow.com/a/29754866
|
# https://stackoverflow.com/a/29754866
|
||||||
OPTIONS=s:d:t:c::a::v::hj::pwm:
|
OPTIONS=s:d:t:c::a::v::hj::
|
||||||
LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help,jobs::,playlists,windows-format,mapping:
|
LONGOPTS=source:,dest:,temp:,convert::,resize-art::,verbose::,help,jobs::
|
||||||
|
|
||||||
# -use ! and PIPESTATUS to get exit code with errexit set
|
# -use ! and PIPESTATUS to get exit code with errexit set
|
||||||
# -temporarily store output to be able to check for errors
|
# -temporarily store output to be able to check for errors
|
||||||
@ -161,13 +139,14 @@ GetOptions() {
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# read getopt's output this way to handle the quoting right:
|
# read getopt’s output this way to handle the quoting right:
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
# now enjoy the options in order and nicely split until we see --
|
# now enjoy the options in order and nicely split until we see --
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-v|--verbose)
|
-v|--verbose)
|
||||||
|
verbose=2
|
||||||
if [[ $2 != "" ]]; then
|
if [[ $2 != "" ]]; then
|
||||||
verbose=${2}
|
verbose=${2}
|
||||||
fi
|
fi
|
||||||
@ -198,6 +177,7 @@ GetOptions() {
|
|||||||
-c|--convert)
|
-c|--convert)
|
||||||
VerboseOutput 0 "--convert given"
|
VerboseOutput 0 "--convert given"
|
||||||
convert=true
|
convert=true
|
||||||
|
bitrate=192
|
||||||
if [[ $2 != "" ]]; then
|
if [[ $2 != "" ]]; then
|
||||||
bitrate=${2}
|
bitrate=${2}
|
||||||
fi
|
fi
|
||||||
@ -207,6 +187,7 @@ GetOptions() {
|
|||||||
-a|--resize-art)
|
-a|--resize-art)
|
||||||
VerboseOutput 0 "--resize-art given"
|
VerboseOutput 0 "--resize-art given"
|
||||||
convertart=true
|
convertart=true
|
||||||
|
coverartsize=200
|
||||||
if [[ $2 != "" ]]; then
|
if [[ $2 != "" ]]; then
|
||||||
coverartsize=${2}
|
coverartsize=${2}
|
||||||
fi
|
fi
|
||||||
@ -216,32 +197,13 @@ GetOptions() {
|
|||||||
-j|--jobs)
|
-j|--jobs)
|
||||||
VerboseOutput 0 "--jobs given"
|
VerboseOutput 0 "--jobs given"
|
||||||
multithread=true
|
multithread=true
|
||||||
|
jobcount=$(expr $(nproc) - 2)
|
||||||
if [[ $2 != "" ]]; then
|
if [[ $2 != "" ]]; then
|
||||||
jobcount=${2}
|
jobcount=${2}
|
||||||
fi
|
fi
|
||||||
shift 2
|
shift 2
|
||||||
VerboseOutput 1 "Multithreading will use ${jobcount} threads"
|
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//,/ })
|
|
||||||
mappingsrc=${listmappingparam[0]:-""}
|
|
||||||
mappingdest=${listmappingparam[1]:-""}
|
|
||||||
shift 2
|
|
||||||
VerboseOutput 1 "Playlist mappings enabled source=${mappingsrc} dest=${mappingdest}"
|
|
||||||
;;
|
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@ -318,22 +280,22 @@ CreateFileList() {
|
|||||||
origfile="${file#"$1/"}"
|
origfile="${file#"$1/"}"
|
||||||
relfile=$(echo ${origfile} | sed -e 's/\(\.\)*$//g' | tr -s ' ')
|
relfile=$(echo ${origfile} | sed -e 's/\(\.\)*$//g' | tr -s ' ')
|
||||||
mp3file=$(echo "${relfile}" | sed -e 's/.flac/.mp3/')
|
mp3file=$(echo "${relfile}" | sed -e 's/.flac/.mp3/')
|
||||||
VerboseOutput 0 "Checking ${3}${origfile}"
|
VerboseOutput 0 "Checking ${origfile}"
|
||||||
if [[ -d "${1}/$origfile" ]]; then
|
if [[ -d "${1}/$origfile" ]]; then
|
||||||
VerboseOutput 0 "${origfile} is folder"
|
VerboseOutput 0 "${origfile} is folder"
|
||||||
newdir="${3}$origfile"
|
newdir="${3}/$origfile"
|
||||||
newdir=${newdir#"/"}
|
newdir=${newdir#"/"}
|
||||||
VerboseOutput 1 "Entering $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
|
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 0 "${origfile} is newer in source"
|
||||||
VerboseOutput 2 "Added: ${3}${origfile}"
|
VerboseOutput 2 "Added: ${3}/${origfile}"
|
||||||
elif [[ $playlists == true ]] && [[ "${1}/$origfile" == *".m3u" ]] && [[ "${1}/$origfile" -nt "${2}/$mp3file" ]]; then
|
|
||||||
echo ${3}$origfile >> /tmp/music-sync-filelist
|
|
||||||
VerboseOutput 0 "${origfile} is newer in source"
|
|
||||||
VerboseOutput 2 "Added playlist: ${3}${origfile}"
|
|
||||||
fi
|
fi
|
||||||
|
if [[ "${1}/$origfile" == *".m3u" ]]; then
|
||||||
|
VerboseOutput 0 "${origfile} is playlist"
|
||||||
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +308,6 @@ Execute() {
|
|||||||
VerboseOutput 3 "Running in parallel. Mind your load"
|
VerboseOutput 3 "Running in parallel. Mind your load"
|
||||||
export -f ProcessFile
|
export -f ProcessFile
|
||||||
export -f ConvertFile
|
export -f ConvertFile
|
||||||
export -f ConvertPlaylist
|
|
||||||
export -f CopyFile
|
export -f CopyFile
|
||||||
export -f VerboseOutput
|
export -f VerboseOutput
|
||||||
export -f ExecTime
|
export -f ExecTime
|
||||||
@ -358,13 +319,16 @@ Execute() {
|
|||||||
export verbose
|
export verbose
|
||||||
export coverartsize
|
export coverartsize
|
||||||
export begin
|
export begin
|
||||||
export windowspaths
|
|
||||||
export mappingsrc
|
|
||||||
export mappingdest
|
|
||||||
parallel --jobs ${jobcount} --will-cite --line-buffer --arg-file "/tmp/music-sync-filelist" ProcessFile
|
parallel --jobs ${jobcount} --will-cite --line-buffer --arg-file "/tmp/music-sync-filelist" ProcessFile
|
||||||
else
|
else
|
||||||
for line in $(cat "/tmp/music-sync-filelist")
|
for line in $(cat "/tmp/music-sync-filelist")
|
||||||
do
|
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
|
ProcessFile $line
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
@ -379,56 +343,11 @@ ProcessFile() {
|
|||||||
VerboseOutput 2 "Current File: $line"
|
VerboseOutput 2 "Current File: $line"
|
||||||
VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%)"
|
VerboseOutput 2 "Progress: $curline / $total (${percentage%00}%)"
|
||||||
if [[ $convert == true ]]; then
|
if [[ $convert == true ]]; then
|
||||||
if [[ $line == *".m3u" ]]; then
|
|
||||||
ConvertPlaylist "$line"
|
|
||||||
else
|
|
||||||
ConvertFile "$line"
|
ConvertFile "$line"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
CopyFile "$line"
|
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
|
|
||||||
VerboseOutput 0 "Creating playlist $temp/$line"
|
|
||||||
IFS="
|
|
||||||
"
|
|
||||||
for item in $(cat "$source/$line")
|
|
||||||
do
|
|
||||||
mp3item=$(echo $item | sed -e 's/\.*\//\//g'| tr -s ' ')
|
|
||||||
if [[ $convert == true ]]; then
|
|
||||||
mp3item=$(echo "$item" | sed -e 's/.flac/.mp3/')
|
|
||||||
else
|
|
||||||
mp3item=$(echo "$item")
|
|
||||||
fi
|
|
||||||
playline=$(echo "${mp3item}" | sed -e "s,$mappingsrc,$mappingdest,g")
|
|
||||||
if [[ $windowspaths == true ]]; then
|
|
||||||
playline=$(echo "${playline}" | sed -e 's,\/,\\,g')
|
|
||||||
fi
|
|
||||||
echo $playline >> $temp/$line
|
|
||||||
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() {
|
ConvertFile() {
|
||||||
line=${1}
|
line=${1}
|
||||||
if [[ ! -f "${source}/$line" ]]; then
|
if [[ ! -f "${source}/$line" ]]; then
|
||||||
@ -437,12 +356,12 @@ ConvertFile() {
|
|||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d $(dirname "$temp/$line") ]]; then
|
if [[ "$temp/$line" = */* ]]; then
|
||||||
VerboseOutput 0 "Creating folder $temp/${line%/*}"
|
VerboseOutput 0 "Creating folder $temp/${line%/*}"
|
||||||
mkdir -p "$temp/${line%/*}";
|
mkdir -p "$temp/${line%/*}";
|
||||||
fi;
|
fi;
|
||||||
mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/')
|
mp3line=$(echo "$line" | sed -e 's/.flac/.mp3/')
|
||||||
if [[ "${source}/$line" -nt "$temp/$mp3line" ]]; then
|
if [[ ! -f "$temp/$mp3line" || "${source}/$mp3line" -nt "$temp/$mp3line" ]]; then
|
||||||
if [[ $line != *".mp3" ]]; then
|
if [[ $line != *".mp3" ]]; then
|
||||||
VerboseOutput 3 "${line} will be converted to mp3-file ${mp3line}"
|
VerboseOutput 3 "${line} will be converted to mp3-file ${mp3line}"
|
||||||
fi
|
fi
|
||||||
@ -494,7 +413,7 @@ CopyFile() {
|
|||||||
destline=$(echo $mp3line | sed -e 's/\.*\//\//g'| tr -s ' ')
|
destline=$(echo $mp3line | sed -e 's/\.*\//\//g'| tr -s ' ')
|
||||||
VerboseOutput 1 "Copying: $line"
|
VerboseOutput 1 "Copying: $line"
|
||||||
|
|
||||||
if [[ ! -d $(dirname "$dest/$line") ]]; then
|
if [[ "$dest/$line" = */* ]]; then
|
||||||
VerboseOutput 0 "Creating folder $dest/${line%/*}"
|
VerboseOutput 0 "Creating folder $dest/${line%/*}"
|
||||||
mkdir -p "$dest/${destline%/*}";
|
mkdir -p "$dest/${destline%/*}";
|
||||||
fi;
|
fi;
|
||||||
@ -552,18 +471,9 @@ if [[ ! -f /tmp/music-sync-filelist ]]; then
|
|||||||
CleanUp
|
CleanUp
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
if [[ $convert == false ]]; then
|
||||||
if [[ $convert == true ]]; then
|
|
||||||
temp=${temp}/bitrate-${bitrate}
|
|
||||||
if [[ $convertart == true ]]; then
|
|
||||||
temp="${temp}/coverart-${coverartsize}"
|
|
||||||
else
|
|
||||||
temp="${temp}/coverart-original"
|
|
||||||
fi
|
|
||||||
VerboseOutput 2 "Conversion enabled. Using $temp as temp-folder"
|
|
||||||
else
|
|
||||||
if [[ $temp != "/tmp/converted" ]]; then
|
if [[ $temp != "/tmp/converted" ]]; then
|
||||||
VerboseOutput 2 "Conversion not enabled. Ignoring temp folder"
|
VerboseOutput 2 "Conversion not enabled. Ignoring cache folder"
|
||||||
fi
|
fi
|
||||||
temp=$source
|
temp=$source
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user