mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 09:50:09 +00:00
402 lines
8.1 KiB
Bash
Executable File
402 lines
8.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# TODO add option to continue last sync...
|
|
# - need to store parsable log
|
|
# - settings
|
|
# - started/completed operations
|
|
# - all operations should be resumable
|
|
|
|
VERSION=1.0
|
|
|
|
DATE=`date +%Y%m%d`
|
|
COUNT=1
|
|
TITLE=""
|
|
|
|
RSYNC=rsync
|
|
#RSYNCFLAGS="-arptgoA --info=progress2,flist --human-readable"
|
|
RSYNCFLAGS="-arpt --info=progress2,flist --human-readable"
|
|
|
|
CP=cp
|
|
CPFLAGS=-Rpfv
|
|
|
|
# override default...
|
|
COPY=$RSYNC
|
|
COPYFLAGS=$RSYNCFLAGS
|
|
|
|
# NOTE: jdupes reports progress to stderr and output to stdout...
|
|
# XXX need to test if this exists...
|
|
VERIFY=jdupes
|
|
VERIFYFLAGS="-r -u -I"
|
|
DO_VERIFY=
|
|
|
|
|
|
COMPRESS=./compress-archive.sh
|
|
DO_COMPRESS=1
|
|
|
|
SNAPSHOT=../../../../snapshot.sh
|
|
|
|
|
|
# Config file to contain all the default settings...
|
|
# XXX not sure if this is a good idea...
|
|
# ...should we also check file sec?
|
|
##CONFIG=.sync-flash.rc
|
|
##if ! [ -z $CONFIG ] && [ -e ~/$CONFIG ] ; then
|
|
## # XXX executing an external file...
|
|
## source ~/$CONFIG
|
|
##fi
|
|
|
|
|
|
# base mount dir...
|
|
BASES=(
|
|
/Volumes
|
|
/cygdrive
|
|
/run/media/$USER
|
|
/mnt
|
|
~/mnt
|
|
)
|
|
i=0
|
|
for d in "${BASES[@]}"; do
|
|
# normalize...
|
|
BASES[$i]="${d%/}/"
|
|
# remove non-existant bases...
|
|
if ! [ -d "$d" ] ; then
|
|
unset BASES[$i]
|
|
elif [ -z $BASE ] ; then
|
|
BASE=$d
|
|
fi
|
|
i=$(( i + 1 ))
|
|
done
|
|
|
|
|
|
while true ; do
|
|
case "$1" in
|
|
-h|-help|--help)
|
|
echo "usage: `basename $0` FLAGS DRIVE [TITLE]"
|
|
echo
|
|
echo " -h|-help print this message and exit."
|
|
echo " -m|-multi single base, multiple sub dirs"
|
|
echo " for multiple flash cards in a"
|
|
echo " single shoot."
|
|
echo " -l|-last last flash card in set, run"
|
|
echo " process-archive.sh after copying."
|
|
echo " -b|-base BASE the base dir to look for drives in"
|
|
echo " default: $BASE"
|
|
echo " --rsync use rsync (default)"
|
|
echo " --cp use cp"
|
|
if ! [ -z $VERIFY ] ; then
|
|
echo " --verify toggle copy verification"
|
|
echo " default: `[[ $DO_VERIFY ]] && echo "on" || echo "off"`"
|
|
fi
|
|
if ! [ -z $COMPRESS ] ; then
|
|
echo " --compress toggle archive compression"
|
|
echo " default: `[[ $DO_COMPRESS ]] && echo "on" || echo "off"`"
|
|
fi
|
|
# notes...
|
|
echo
|
|
if ! [ -z $COMPRESS ] ; then
|
|
echo "NOTE: the index is fully usable during the compression stage"
|
|
fi
|
|
echo "NOTE: cp under Cygwin may messup permissions, use rsync."
|
|
echo
|
|
exit
|
|
;;
|
|
|
|
-i|--interactive)
|
|
INTERACTIVE=1
|
|
shift
|
|
;;
|
|
-m|-multi|--multi)
|
|
MULTI=1
|
|
shift
|
|
;;
|
|
-l|-last|--last)
|
|
LAST=1
|
|
shift
|
|
;;
|
|
-b|-base|--base)
|
|
BASE=$2
|
|
shift 2
|
|
;;
|
|
-cp|--cp)
|
|
COPY=cp
|
|
COPYFLAGS=-Rpfv
|
|
shift
|
|
break
|
|
;;
|
|
-rsync|--rsync)
|
|
COPY=$RSYNC
|
|
COPYFLAGS=$RSYNCFLAGS
|
|
shift
|
|
break
|
|
;;
|
|
-verify|--verify)
|
|
DO_VERIFY=`[[ $DO_VERIFY ]] && echo "" || echo 1`
|
|
shift
|
|
break
|
|
;;
|
|
-compress|--compress)
|
|
DO_COMPRESS=`[[ $DO_COMPRESS ]] && echo "" || echo 1`
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if ! [ -z "$2" ] ; then
|
|
TITLE=" - $2"
|
|
fi
|
|
|
|
BASE=${BASE%/}/
|
|
DRIVE=${1}
|
|
|
|
__BASE=$BASE
|
|
while true ; do
|
|
BASE=$__BASE
|
|
if [[ $INTERACTIVE || ! $DRIVE ]] ; then
|
|
INTERACTIVE=1
|
|
echo
|
|
echo "Select/toggle an option:"
|
|
if [ -z $MULTI_STARTED ] ; then
|
|
if [[ $MULTI ]] ; then
|
|
echo "0) Multiple flash cards"
|
|
else
|
|
echo "0) Single flash card"
|
|
fi
|
|
else
|
|
echo "0) Build after this flash card: `[[ $LAST ]] && echo "yes" || echo "no"`"
|
|
fi
|
|
echo "1) Directoy description is: \"$TITLE\""
|
|
echo "a-z|name) Type a drive letter, mount name in $BASE or path and start"
|
|
echo " (paths must start with \"/\", \"./\" or \"[A-Z]:\")"
|
|
if [[ $DRIVE ]] ; then
|
|
echo "Enter) Copy drive ${DRIVE}"
|
|
fi
|
|
echo "2) Build"
|
|
|
|
# dynamic options...
|
|
i=3
|
|
OPTION_VERIFICATION=
|
|
if ! [ -z $VERIFY ] ; then
|
|
echo "$i) Verification is `[[ $DO_VERIFY ]] && echo "on" || echo "off"`"
|
|
OPTION_VERIFICATION=$i
|
|
i=$(( i + 1 ))
|
|
fi
|
|
|
|
OPTION_COMPRESSION=
|
|
if ! [ -z $COMPRESS ] ; then
|
|
echo "$i) Compresion is `[[ $DO_COMPRESS ]] && echo "on" || echo "off"`"
|
|
OPTION_COMPRESSION=$i
|
|
i=$(( i + 1 ))
|
|
fi
|
|
|
|
echo "$i) Quit"
|
|
OPTION_QUIT=$i
|
|
read -ep ": " RES
|
|
|
|
# NOTE: we can't use letters here as they will shadow
|
|
# with drive letters...
|
|
case $RES in
|
|
# toggle multi mode...
|
|
0)
|
|
if [ -z $MULTI_STARTED ] ; then
|
|
MULTI=`[[ ! $MULTI ]] && echo 1 || echo ""`
|
|
else
|
|
LAST=`[[ ! $LAST ]] && echo 1 || echo ""`
|
|
fi
|
|
continue
|
|
;;
|
|
1)
|
|
read -i "${TITLE# - }" -ep "new description: " TITLE
|
|
TITLE=" - $TITLE"
|
|
continue
|
|
;;
|
|
# continue with same drive or ask again...
|
|
"")
|
|
if [[ ! $DRIVE ]] ; then
|
|
echo "ERR: need a drive to copy from, no defaults."
|
|
echo
|
|
continue
|
|
fi
|
|
DRIVE=$DRIVE
|
|
;;
|
|
2)
|
|
LAST=1
|
|
break
|
|
;;
|
|
|
|
# dynamic option handlers...
|
|
"$OPTION_VERIFICATION")
|
|
DO_VERIFY=`[[ ! $DO_VERIFY ]] && echo 1 || echo ""`
|
|
continue
|
|
;;
|
|
"$OPTION_COMPRESSION")
|
|
DO_COMPRESS=`[[ ! $DO_COMPRESS ]] && echo 1 || echo ""`
|
|
continue
|
|
;;
|
|
"$OPTION_QUIT")
|
|
exit
|
|
;;
|
|
|
|
# new drive letter...
|
|
*)
|
|
DRIVE=$RES
|
|
;;
|
|
esac
|
|
echo
|
|
fi
|
|
|
|
# explicit path given...
|
|
if [[ "${DRIVE::1}" == "/" ]] \
|
|
|| [[ "${DRIVE::2}" == "./" ]] \
|
|
|| [[ "${DRIVE::2}" =~ [a-zA-Z]: ]] \
|
|
&& [ -e "$DRIVE" ] ; then
|
|
BASE=
|
|
fi
|
|
|
|
# check path...
|
|
notfound=()
|
|
if ! [ -z $BASE ] ; then
|
|
for d in "${BASES[@]}"; do
|
|
if [ -e "${d}${DRIVE}" ] ; then
|
|
BASE=$d
|
|
break
|
|
else
|
|
notfound+=("${d}${DRIVE}")
|
|
fi
|
|
i=$(( i + 1 ))
|
|
done
|
|
fi
|
|
if ! [ -e "${BASE}${DRIVE}" ] ; then
|
|
if [ ${#notfound[@]} == 0 ] ; then
|
|
notfound=(${BASE}${DRIVE})
|
|
fi
|
|
echo
|
|
echo "ERR: Not found:"
|
|
for d in "${notfound[@]}" ; do
|
|
echo "ERR: ${d}"
|
|
done
|
|
echo "ERR: Nothing to copy."
|
|
echo
|
|
if [[ $INTERACTIVE || ! $DRIVE ]] ; then
|
|
continue
|
|
fi
|
|
exit
|
|
fi
|
|
|
|
# XXX do a real three digit count...
|
|
# single flash card...
|
|
SCOUNT=`printf "%03d" $COUNT`
|
|
if [ -z $MULTI ] ; then
|
|
DIR="${DATE}.${SCOUNT}${TITLE}"
|
|
while [ -e *"$DIR"* ] ; do
|
|
COUNT=$((COUNT+1))
|
|
SCOUNT=`printf "%03d" $COUNT`
|
|
DIR="${DATE}.${SCOUNT}${TITLE}"
|
|
done
|
|
BASE_DIR=$DIR
|
|
|
|
# multiple flash cards shoot...
|
|
else
|
|
BASE_DIR="${DATE}${TITLE}/"
|
|
DIR="${BASE_DIR}/${DATE}.${SCOUNT}"
|
|
# get next dir index...
|
|
while [ -e *"$DIR"* ] ; do
|
|
COUNT=$((COUNT+1))
|
|
SCOUNT=`printf "%03d" $COUNT`
|
|
DIR="${BASE_DIR}/${DATE}.${SCOUNT}"
|
|
done
|
|
fi
|
|
|
|
MULTI_STARTED=1
|
|
|
|
# normalize paths...
|
|
BASE_DIR="./- ${BASE_DIR}/"
|
|
DIR="./- $DIR/"
|
|
|
|
mkdir -vp "$DIR"
|
|
|
|
while true ; do
|
|
echo "Copying files from ${BASE}${DRIVE} (~`du -hs "${BASE}${DRIVE}" | cut -f 1`)..."
|
|
#echo "# $COPY $COPYFLAGS ${BASE}${DRIVE}/* "$DIR""
|
|
#echo "# 2> >(tee "${DIR}"/copy-err.log)"
|
|
$COPY $COPYFLAGS ${BASE}${DRIVE}/* "$DIR" \
|
|
2> >(tee "${DIR}"/copy-err.log)
|
|
# no errors -> remove log...
|
|
if ! [ -s "${DIR}/copy-err.log" ] ; then
|
|
rm -f "${DIR}"/copy-err.log
|
|
fi
|
|
echo "Copying files: done."
|
|
|
|
# verify copy...
|
|
# XXX make this more generic...
|
|
if [ $DO_VERIFY ] && ! [ -z $VERIFY ] ; then
|
|
echo "Verifying copied files..."
|
|
$VERIFY $VERIFYFLAGS ${BASE}${DRIVE}/* "$DIR" \
|
|
> >(tee "${DIR}"/verification-err.log)
|
|
if ! [ -s "${DIR}/verification-err.log" ] ; then
|
|
rm -f "${DIR}"/verification-err.log
|
|
else
|
|
echo
|
|
echo "WARNING: found mismatching files"
|
|
echo " (see: "${DIR}"/verification-err.log)"
|
|
echo
|
|
while true; do
|
|
read -ep "[R]etry, [c]ontinue, or Ctrl-C to cancel: " ACTION
|
|
ACTION=`echo ${ACTION,,} | xargs`
|
|
if [[ $ACTION =~ [rc] ]] \
|
|
|| [ -z $ACTION ] ; then
|
|
break
|
|
fi
|
|
echo "Unknown input: \"$ACTION\""
|
|
done
|
|
if [[ $ACTION == "c" ]] ; then
|
|
break
|
|
else
|
|
continue
|
|
fi
|
|
fi
|
|
echo "Verifification: done."
|
|
break
|
|
# no verification defined...
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
|
|
# exit interactive mode...
|
|
if [[ ! $MULTI || ! $INTERACTIVE || $LAST ]] ; then
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [[ $LAST ]] ; then
|
|
COMMON_FLAG=-c
|
|
fi
|
|
|
|
if [[ ! $MULTI || $LAST ]] ; then
|
|
echo "Building archive..."
|
|
./process-archive.sh $COMMON_FLAG "$BASE_DIR"
|
|
echo "Building archive: done."
|
|
fi
|
|
|
|
if [[ $DO_COMPRESS ]] ; then
|
|
echo "Compressing archive..."
|
|
${COMPRESS} "$BASE_DIR"
|
|
echo "Compressing archive: done."
|
|
fi
|
|
|
|
if ! [ -z "$SNAPSHOT" ] \
|
|
&& [ -e "$SNAPSHOT" ] ; then
|
|
"$SNAPSHOT"
|
|
fi
|
|
|
|
# XXX add report...
|
|
# XXX
|
|
|
|
echo "`basename "$0"`: done."
|
|
|
|
# vim:set nowrap :
|