Skip to content

Instantly share code, notes, and snippets.

@riyad
Last active December 18, 2022 15:57
Show Gist options
  • Save riyad/d4d7f77a369b76cd1ffd to your computer and use it in GitHub Desktop.
Save riyad/d4d7f77a369b76cd1ffd to your computer and use it in GitHub Desktop.
Synchronize directories between computers using rsync (and SSH)
#!/usr/bin/env python3
#
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de>
# License: Mozilla Public License 2.0
#
# Synchronize directories between computers using rsync (and SSH).
#
# INSTALLATION:
# Save this script as something like `sync-to` somewhere in $PATH.
# Link it to `sync-from` in the same location. (i.e. `ln sync-to sync-from`)
import os
import re
import shlex
import subprocess
import sys
PROGRAM_NAME = os.path.basename(sys.argv[0])
RSYNC = 'rsync'
RSYNC_BASIC_OPTIONS = [
'--rsh="ssh"', '--partial', '--progress', '--archive', '--human-readable']
RSYNC_EXCLUDE_PATTERNS = ['.DS_Store', '.localized']
#
# helpers
#
def print_usage_and_die():
print(re.sub(r'^[ ]{8}', '',
f"""
Synchronize directories between computers using rsync (and SSH).
Usage: {PROGRAM_NAME} HOST DIR [options]
HOST any host you'd use with SSH
DIR must be available on both the local and the remote machine
Options:
You can pass any options rsync accepts.
-v, --verbose will also print the command that'll be used to sync
Examples:
sync-to other-pc ~/Documents
sync-to other-pc ~/Music --exclude '*.wav'
sync-from other-pc ~/Music --dry-run --delete
""".strip(),
flags=re.MULTILINE
))
exit(1)
def is_verbose():
return any(
re.search(r'^--verbose|-\w*v\w*$', arg) is not None
for arg
in sys.argv
)
#
# main
#
def main():
#
# parse options
#
if len(sys.argv) < 3:
print_usage_and_die()
host = sys.argv[1]
dir = sys.argv[2]
rsync_excludes = [f"--exclude='{pattern}'" for pattern in RSYNC_EXCLUDE_PATTERNS]
rsync_user_options = sys.argv[3:]
if re.search(r'from$', PROGRAM_NAME):
rsync_src_dest = [f"{host}:{dir}/", dir]
elif re.search(r'to$', PROGRAM_NAME):
rsync_src_dest = [f"{dir}/", f"{host}:{dir}"]
else:
print('Error: unknown command')
print_usage_and_die()
#
# copy
#
exec_args = RSYNC_BASIC_OPTIONS + rsync_excludes + rsync_user_options + rsync_src_dest
if is_verbose():
print(f"{RSYNC} {' '.join(RSYNC_BASIC_OPTIONS + rsync_excludes)} {shlex.join(rsync_user_options + rsync_src_dest)}")
os.execvp(RSYNC, exec_args)
#subprocess.run([RSYNC] + exec_args)
if __name__ == '__main__':
main()
@riyad
Copy link
Author

riyad commented Jan 31, 2015

Installation

  • Save this script as something like sync-to somewhere in $PATH.
  • Link it to sync-from in the same location. (i.e. ln sync-to sync-from)

Examples

sync-to other-pc ~/Documents
sync-to other-pc ~/Music --exclude '*.wav'
sync-fom other-pc ~/Music --dry-run --delete

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment