21

I'd like to automatically run a one way sync between two local directories using rsync. Meaning when a change is detected in a file of /dir1 or its subdirs, the following command should run:

rsync -rtuv /dir1 /dir2

How can I go about achieving this with fswatch?

Is it possible to supply arguments for rsync to only copy the actual files that were changed, as given by the fswatch events?

OpherV
  • 6,787
  • 6
  • 36
  • 55
  • Ask on https://apple.stackexchange.com or https://unix.stackexchange.com – trojanfoe Jan 03 '16 at 10:15
  • `rsync` is already pretty optimal about only doing the minimum necessary updates - why not just go with `fswatch . | while read f; do echo rsync; done` ? http://bryanpendleton.blogspot.co.uk/2010/05/rsync-algorithm.html – Mark Setchell Jan 03 '16 at 12:20

2 Answers2

39
alias run_rsync='rsync -azP --exclude ".*/" --exclude ".*" --exclude "tmp/" ~/Documents/repos/my_repository username@host:~'
run_rsync; fswatch -o . | while read f; do run_rsync; done

Second line runs run_rsync once unconditionally and then - on each change in current directory (or specify exact path instead of .)

Rsync options:

  • -a - stands for "archive" and syncs recursively and preserves symbolic links, special and device files, modification times, group, owner, and permissions.
  • -z - compression
  • -P - combines the flags --progress and --partial. The first of these gives you a progress bar for the transfers and the second allows you to resume interrupted transfers
  • --exclude - excludes files by pattern

You will need fswatch:

brew install fswatch
Daniel Garmoshka
  • 5,849
  • 39
  • 40
  • 7
    Very nice ninja post. Perhaps using `-or` after `fswatch` would be better, for recursiveness. – Zoltán Feb 27 '17 at 22:12
  • 2
    Beware: fswatch scans entire tree even if you exclude things. https://github.com/emcrisostomo/fswatch/issues/151. That is, your `node_modules` if you have one will be completely scanned. – vaughan Jul 19 '18 at 15:05
  • Wouldn't this call rsync for every changed file, while it only needs to be called ones since rsync also checks what files have changed? – Visionscaper Aug 26 '20 at 13:03
  • No, the -o option means --one-per-batch. See here: https://github.com/emcrisostomo/fswatch/wiki/How-to-Use-fswatch#bubbling-events. – Brian Nov 18 '21 at 03:25
  • @vaughan Oops that is huge. Is there any workarounds? – ch271828n Mar 03 '22 at 08:57
2

For a one-line solution:

function run_rsync() { rsync your_args } ; run_rsync; fswatch -o your_directory | while read f; do run_rsync; done

Thanks @Daniel for the inspiring answer.

ch271828n
  • 15,854
  • 5
  • 53
  • 88