Skip to content

Instantly share code, notes, and snippets.

@taskie
Last active October 30, 2018 15:33
Show Gist options
  • Save taskie/d55350fb1cb900012c6d91abf6bf14cc to your computer and use it in GitHub Desktop.
Save taskie/d55350fb1cb900012c6d91abf6bf14cc to your computer and use it in GitHub Desktop.
diff then cp
set -eu
PROGRAM="$(basename "$0")"
usage () {
cat <<EOF
${PROGRAM}: diff then cp
Usage:
${PROGRAM} [-f|-i] SRC DEST
Options:
-f, --force
-i, --interactive
--diff DIFF
--diffopts DIFFOPTS
-e, --error
-v, --verbose
-g, --debug
-h, --help
EOF
}
MODE=interactive
VERBOSITY=0
DIFF="${DCP_DIFF:-diff}"
DIFFOPTS="${DCP_DIFFOPTS:--u}"
ERROR=
OPTIND=1
DEBUG=
parse_opts () {
OPTIND=1
while [ $# -ne 0 ]; do
case "$1" in
-f|--force)
MODE=force
;;
-i|--interactive)
MODE=interactive
;;
--diff)
DIFF="$2"
OPTIND="$(expr "$OPTIND" + 1)"
shift
;;
--diffopts)
DIFFOPTS="$2"
OPTIND="$(expr "$OPTIND" + 1)"
shift
;;
-e|--error)
ERROR=1
;;
-v|--verbose)
VERBOSITY="$(expr "$VERBOSITY" + 1)"
;;
-g|--debug)
DEBUG=1
;;
-h|--help)
usage
exit 0
;;
-)
return
;;
-*)
usage
echo >&2
echo >&2 "invalid option: $1"
exit 1
;;
*)
return
;;
esac
OPTIND="$(expr "$OPTIND" + 1)"
shift
done
}
parse_opts "$@"
shift "$(expr "$OPTIND" - 1)"
if [ $# -ne 2 ]; then
usage
echo >&2
echo >&2 "you must specify just 2 arguments"
exit 1
fi
SRC="$1"
DEST="$2"
shift 2
if [ -n "$DEBUG" ]; then
cat >&2 <<EOF
MODE=${MODE}
VERBOSITY=${VERBOSITY}
DIFF=${DIFF}
DIFFOPTS=${DIFFOPTS}
ERROR=${ERROR}
SRC=${SRC}
DEST=${DEST}
EOF
fi
if [ "$DEST" = - ]; then
echo >&2 "destination must not be -"
exit 1
fi
if [ "$MODE" = interactive -a ! -t 0 ]; then
echo >&2 "stdin is not a tty. use -f (--force) option"
exit 1
fi
rm_tmp_src () {
[ -e "$SRC" ] && rm -f "$SRC" || :
}
if [ "$SRC" = - ]; then
SRC="$(mktemp "${PROGRAM}-XXXXXX")"
trap rm_tmp_src EXIT HUP INT TERM
cat >"$SRC"
fi
if [ ! -e "$DEST" ]; then
if [ -n "$ERROR" ]; then
echo >&2 "no such file: ${DEST}"
exit 10
fi
elif "$DIFF" $DIFFOPTS "$DEST" "$SRC"; then
if [ -n "$ERROR" ]; then
echo >&2 'no difference'
exit 11
else
exit 0
fi
fi
# has difference
case "$MODE" in
interactive)
cp -iT "$SRC" "$DEST"
;;
force)
cp -fT "$SRC" "$DEST"
;;
*)
echo >&2 "invalid mode: ${MODE}"
exit 1
;;
esac
if [ "$VERBOSITY" -ge 3 ]; then
if command -v cowsay >/dev/null 2>&1; then
cowsay >&2 "completed."
else
echo >&2 "completed."
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment