Last active
August 22, 2024 04:20
-
-
Save allex/5dd8c160752333dc041cd5a222c06a1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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