91 lines
2.5 KiB
Bash
Executable File
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 $?
|