There's always time to play

Thursday, August 26, 2010

rsync with --delete-excluded

While setting up daily (offsite) automated backups I ran into a few issues. First of all backups didn't complete before people were getting to work again, so I had to manually stop them and start them at a lower transferrate. This is easily done by passing rsync the --bwlimit=<kbps> option.

Next I often want to sync just part of the tree, so I would add --exclude=/<folder> to the options to exclude all folders I don't want. However, I also exclude some files and I use --delete, which has the nasty side-effect of not deleting the excluded files on the receiving end (if they were deleted on the sender), thus leaving non-empty folders on the receiver and generating errors because the non-empty folders aren't deleted. There's an option that 'fixes' this, and that's --delete-excluded. This option will delete excluded files on the receiving end. You can guess that combined with my --exclude=/<folder> this would result in deleting an entire branch of the tree that should not be removed... The solution is to specify that the exclude is a receiving side exclude, because excludes are server side exclude by default when --delete-excluded is also provided. This can be done by using a filter rule instead of an exclude rule, resulting in the following option: --filter=-r_/<folder>. The - is to specify it's an exclude, the r specifies it's for the receiving side and the _ seperates the modifiers from the path (space is also allowed, but using an underscore prevents the need for quoting or even double-quoting). Now there's one nasty issue remaining: the excluded folder will still be parsed on the sender, so let's make it an exclude for both sender and receiver: --filter=-rs_/<folder>.

Using the above it's now possible to exclude files from an rsync transfer, without removing them on the receiving side, but with deletion of exclude files on the receiving end. In short: rsync --exclude='*.tmp' --filter='-rs_/important/' --delete --delete-excluded <source> <dest> will leave the important folder alone on the destination, but will remove all .tmp files in the destination.