211 lines
4.7 KiB
Bash
Executable File
211 lines
4.7 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
begin=$(date +"%s")
|
||
# saner programming env: these switches turn some bugs into errors
|
||
set -o errexit -o pipefail -o noclobber -o nounset
|
||
source="-"
|
||
dest="-"
|
||
verbose=2
|
||
help=false
|
||
|
||
GetOptions() {
|
||
|
||
# https://stackoverflow.com/a/29754866
|
||
! getopt --test > /dev/null
|
||
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
|
||
VerboseOutput 5 "\`getopt --test\` failed"
|
||
VerboseOutput 5 "Sorry, It seems that your shell is not supported"
|
||
VerboseOutput 5 "If you're using MacOS or another unix-like system, please install GNU getopt"
|
||
exit 1
|
||
fi
|
||
|
||
# Parsing style without -s or -d
|
||
source=${*: -2:1}
|
||
dest=${*: -1:1}
|
||
|
||
OPTIONS=s:d:v::h
|
||
LONGOPTS=source:,dest:,verbose::,help
|
||
|
||
# -use ! and PIPESTATUS to get exit code with errexit set
|
||
# -temporarily store output to be able to check for errors
|
||
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
|
||
# -pass arguments only via -- "$@" to separate them correctly
|
||
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
|
||
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
|
||
# e.g. return value is 1
|
||
# then getopt has complained about wrong arguments to stdout
|
||
Usage
|
||
exit 2
|
||
fi
|
||
|
||
# read getopt’s output this way to handle the quoting right:
|
||
eval set -- "$PARSED"
|
||
|
||
# now enjoy the options in order and nicely split until we see --
|
||
while true; do
|
||
case "$1" in
|
||
-v|--verbose)
|
||
verbose=2
|
||
if [[ $2 != "" ]]; then
|
||
verbose=${2}
|
||
shift
|
||
fi
|
||
shift
|
||
;;
|
||
-h|--help)
|
||
help=true
|
||
shift
|
||
;;
|
||
-s|--source)
|
||
source="$2"
|
||
shift 2
|
||
;;
|
||
-d|--dest)
|
||
dest="$2"
|
||
shift 2
|
||
;;
|
||
--)
|
||
shift
|
||
break
|
||
;;
|
||
*)
|
||
VerboseOutput 5 "Programming error"
|
||
return 3
|
||
;;
|
||
esac
|
||
done
|
||
|
||
if [[ $dest == "" ]] || [[ $source == "" ]]; then
|
||
help=true
|
||
fi
|
||
}
|
||
|
||
Usage() {
|
||
echo ""
|
||
echo "Usage:"
|
||
echo "music-sync <options> -s|--source <source> -d|--dest <destination>"
|
||
echo "music-sync <options> <source> <destination>"
|
||
echo ""
|
||
echo "Syncronises music from one folder to another."
|
||
echo ""
|
||
echo "Options:"
|
||
echo " -s, --source <source> The source folder of the music"
|
||
echo " -d, --dest <destination> The destionation folder of the music"
|
||
echo " -v, --verbose <0-6> Set log level"
|
||
echo " -h, --help Display this help text"
|
||
echo "Log levels:"
|
||
echo " 0 | Verbose"
|
||
echo " 1 | Debug"
|
||
echo " 2 | Info (Default)"
|
||
echo " 3 | Warning"
|
||
echo " 4 | Error"
|
||
echo " 5 | Fatal"
|
||
echo " 6 | No logging"
|
||
echo ""
|
||
}
|
||
|
||
VerboseOutput() {
|
||
level=""
|
||
if [[ $verbose -le $1 ]]; then
|
||
case "$1" in
|
||
0)
|
||
level="\033[1;36mVerbose\033[0m"
|
||
;;
|
||
1)
|
||
level="\033[1;34m Debug \033[0m"
|
||
;;
|
||
2)
|
||
level="\033[1;37m Info \033[0m"
|
||
;;
|
||
3)
|
||
level="\033[1;33mWarning\033[0m"
|
||
;;
|
||
4)
|
||
level="\033[1;31m Error \033[0m"
|
||
;;
|
||
|
||
5)
|
||
level="\033[1;30m Fatal \033[0m"
|
||
;;
|
||
esac
|
||
echo -e "[$level] $2" >&2
|
||
fi
|
||
}
|
||
|
||
CreateFileList() {
|
||
# ${1} /mnt/hdd/Example-Artist/Example-Album
|
||
# ${2} /mnt/mtp/Example-Artist/Example-Album
|
||
# ${3} Example-Artist/Example-Album
|
||
IFS=""
|
||
sourcepath="${1}/*"
|
||
for file in $sourcepath; do
|
||
relfile="${file#"$1/"}"
|
||
if [[ -d "${1}/$relfile" ]]; then
|
||
newdir="${3}/$relfile"
|
||
newdir=${newdir#"/"}
|
||
VerboseOutput 1 "Entering $newdir"
|
||
CreateFileList "${1}/$relfile" "${2}/$relfile" "$newdir"
|
||
elif [[ ! -f "${2}/$relfile" || "${1}/$relfile" -nt "${2}/$relfile" ]]; then
|
||
echo ${3}/$relfile >> /tmp/music-sync-filelist
|
||
VerboseOutput 2 "Added: ${3}/${relfile}"
|
||
fi
|
||
done
|
||
}
|
||
|
||
ConvertFiles() {
|
||
mkdir -p /tmp/converted
|
||
while read -r line
|
||
do
|
||
VerboseOutput 1 "Converting: $line"
|
||
if [[ "/tmp/converted/$line" = */* ]]; then
|
||
mkdir -p "/tmp/converted/${line%/*}";
|
||
fi;
|
||
if [[ ! -f "/tmp/converted/$line" || "${source}/$file" -nt "/tmp/converted/$line" ]]; then
|
||
lame -b 192 $source/$line /tmp/converted/$line 1>/dev/null 2>/dev/null
|
||
VerboseOutput 2 "Converted: $line"
|
||
else
|
||
VerboseOutput 3 "$line already converted"
|
||
fi;
|
||
|
||
done < "/tmp/music-sync-filelist"
|
||
}
|
||
|
||
CopyFiles() {
|
||
while read -r line
|
||
do
|
||
VerboseOutput 1 "Copying: $line"
|
||
if [[ "$dest/$line" = */* ]]; then
|
||
mkdir -p "$dest/${line%/*}";
|
||
fi;
|
||
cp -f $source/$line $dest/$line 1>/dev/null 2>/dev/null
|
||
done < "/tmp/music-sync-filelist"
|
||
VerboseOutput 2 "Copied: $line"
|
||
}
|
||
|
||
CleanUp() {
|
||
VerboseOutput 1 "Cleaning Up"
|
||
rm "/tmp/music-sync-filelist"
|
||
rm -rf "/tmp/converted"
|
||
VerboseOutput 1 "Done"
|
||
}
|
||
|
||
GetOptions $@
|
||
if [[ $help == true ]]; then
|
||
Usage
|
||
exit
|
||
fi
|
||
if [[ -f /tmp/music-sync-filelist ]]; then
|
||
rm /tmp/music-sync-filelist
|
||
fi
|
||
CreateFileList $source $dest ""
|
||
if [[ ! -f /tmp/music-sync-filelist ]]; then
|
||
VerboseOutput 2 "Nothing to do!"
|
||
exit 0
|
||
fi
|
||
ConvertFiles
|
||
CopyFiles
|
||
CleanUp
|
||
|
||
termin=$(date +"%s")
|
||
difftimelps=$(($termin-$begin))
|
||
VerboseOutput 1 "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution." |