Skip to content

Instantly share code, notes, and snippets.

@allex
Last active August 22, 2024 04:20
Show Gist options
  • Save allex/5dd8c160752333dc041cd5a222c06a1e to your computer and use it in GitHub Desktop.
Save allex/5dd8c160752333dc041cd5a222c06a1e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
#
# The `sync-remote-file` is designed to synchronize local and remote files. The
# user can specify the direction of the sync (i.e., whether files are
# transferred from local to remote or remote to local), or can decide at runtime
# when prompted if differences are found.
#
# It accepts an optional argument -d to specify the direction of the sync:
#
# R: sync local file to remote.
# L: sync remote file to local.
#
# Usage:
# sync-remote-file [-d <L|R>] <local-file-path> <remote-file-path>
#
# Example:
# sync-remote-file ./bin/build-cli [email protected]:/mnt/test/usr/local/buildbox/bin/build-cli
#
# by @allex_wang
# Released under the MIT License.
#
# GistID: 5dd8c160752333dc041cd5a222c06a1e
# GistURL: https://gist.github.com/5dd8c160752333dc041cd5a222c06a1e
sync-remote-file() {
local sync_direction
local OPTIND opt
while getopts ":d:" opt; do
case "${opt}" in
d)
sync_direction=${OPTARG}
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
return 1
;;
:)
echo "Option -$OPTARG requires an argument." 1>&2
return 1
;;
esac
done
shift $((OPTIND -1))
if [ $# -ne 2 ]; then
echo "Usage: sync-remote-file [-d <sync-direction,L|R>] <local-file-path> <remote-file-path>"
return 1
fi
local_file="$1"
remote_path="$2"
user_host="${remote_path%%:*}"
remote_file="${remote_path#*:}"
if [ -n "$sync_direction" ] && [ "$sync_direction" != "L" ] && [ "$sync_direction" != "R" ]; then
echo >&2 "fatal: invalid sync direction: [$sync_direction]. Please use either [L] for remote-to-local' or [R] for local-to-remote'"
return 1
fi
# shellcheck disable=SC2029
# Compare the local and remote files in patch diff format
diff_output=$(diff -u <(command ssh "$user_host" cat "$remote_file") "$local_file")
if [ -n "$diff_output" ]; then
# Show the diff and prompt the user to sync
echo "Differences found between local and remote files:"
echo "$diff_output"
if [ -z "$sync_direction" ]; then
read -r -p "Choose the sync action (N to cancel, L for remote-to-local, R for local-to-remote): " choice
else
choice=$sync_direction
fi
case "$choice" in
R|r )
# Copy the local file to the remote host
scp -p "$local_file" "$user_host:$remote_file"
echo "Local file synchronized to remote file."
;;
L|l )
# Copy the remote file to the local host
scp -p "$user_host:$remote_file" "$local_file"
echo "Remote file synchronized to local file."
;;
N|n|"" )
echo "No changes will be made."
;;
* )
echo >&2 "fatal: invalid sync operator '$choice', no changes will be made."
return 1
;;
esac
else
echo "Local and remote files are already in sync."
fi
}
sync-remote-file "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment