icp/icp

91 lines
2.5 KiB
Bash
Executable File

#!/bin/bash
usage() {
echo >&2 "Usage: $(basename $0) [OPTION] SOURCE... DEST"
echo >&2 "Copy like cp, but use rsync in the background."
echo >&2 "Options:"
echo >&2 " -c only transfer files whos checksum does not match"
echo >&2 " -h print this help message"
echo >&2 " -L follow symlinks in source"
echo >&2 " -n no-clobber, do not overwrite existing files"
echo >&2 " -r copy directories recursively"
echo >&2 " -v verbose output"
echo >&2 " --dry-run print rsync command and perform a dry-run"
echo >&2 "Positional arguments:"
echo >&2 " SOURCE file/directory to copy"
echo >&2 " DEST target directory or filename (if only one SOURCE)"
}
# Error codes: rsync compatible
EXIT_SUCCESS=0 # rsync: Success
EXIT_INVALID_OPTION=1 # rsync: Syntax or usage error
EXIT_INVALID_PATH=3 # rsync: Errors selecting input/output files, dirs
# Argument parsing:
# -validate arguments
# -get flags
# -remove trailing slash from directories
flag_recursive=0
flag_dryrun=0
rsync_opt=("-lpgoDu")
rsync_arg=()
for arg in "$@"
do
if [[ "$arg" == "-h" ]];then
usage
exit $EXIT_SUCCESS
elif [[ "$arg" == "-r" ]];then
flag_recursive=1
rsync_opt+=("-r")
elif [[ "$arg" == "-c" ]];then
rsync_opt+=("-c")
elif [[ "$arg" == "-L" ]];then
rsync_opt+=("-L")
elif [[ "$arg" == "-v" ]];then
rsync_opt+=("-v")
elif [[ "$arg" == "-n" ]];then
rsync_opt+=("--ignore-existing")
elif [[ "$arg" == "--dry-run" ]];then
flag_dryrun=1
rsync_opt+=("-nv")
elif [[ -f "$arg" ]];then
rsync_arg+=("$arg")
elif [[ -d "$arg" ]];then
[[ "$arg" == */ ]] && arg="${arg::-1}"
rsync_arg+=("$arg")
elif [[ "$arg" == -* ]];then
echo >&2 "Invalid option: $arg"
exit $EXIT_INVALID_OPTION
else
echo >&2 "Not a file or directory: $arg"
exit $EXIT_INVALID_PATH
fi
done
# Check if we got any actual arguments
if [[ ${#rsync_arg[@]} -lt 2 ]];then
usage
exit $EXIT_INVALID_PATH
fi
# If last argument (target) is a directory
# add a trailing slash
if [[ -d "${rsync_arg[-1]}" ]];then
rsync_arg[-1]="${rsync_arg[-1]}/"
fi
# If this is not a dry-run, add a nice overall
# progress bar
if [[ "$flag_dryrun" -eq 0 ]]; then
rsync_opt+=("--info=progress2 --no-inc-recursive")
fi
# Construct command
cmd="rsync ${rsync_opt[@]} ${rsync_arg[@]}"
# Print the command to stdout if this is a dry-run
if [[ "$flag_dryrun" -eq 1 ]]; then
echo $cmd
fi
# Do the work and return rsync exit code
eval $cmd
exit $?