Rsync –delete-excluded with –prune-empty-dirs, but only prune excluded directories

rsync

I've been using rsync to clone my Windows user profile to a remote server on a nightly basis. I'm using a --filter='merge <file>' arg to load a file full of include/exclude rules, which I use to avoid transferring browser caches and other stuff that I know is useless. I'm also using the --prune-empty-dirs to avoid creating a bunch of unnecessary empty directories.

My script also uses the --delete-excluded switch, because that way if I identify more stuff that I want to exclude, I can just add it to the filter file, and it will automagically get nuked the next time the job runs.

However, this has the side effect of deleting all empty directories. I'm worried that this will break something in the case of a poorly written app that doesn't check for directory existence before writing data.

Is there a way to "prune" only those directories that are empty as a result of exclusions, and not directories that are actually empty on the source side? (I'd like to do this with a simple rule, rather than having to explicitly give any dirs by name, because of the number of dirs involved.)

The only workarounds that immediately come to mind are:

  1. stop using --prune-empty-dirs, and live with the extra directories.
  2. stop using --delete-excluded in the nightly job, and manually run --delete-excluded (without --prune) whenever I change the filter file, which will nuke the new excludes and re-create the "genuinely" empty dirs. Neither is ideal.

Best Answer

You may want to add the directories that are empty on the destination side due to excludes to an exclude filter. If you can exclude the entire directory then your filter rules would be more simple and --prune-empty-dirs may not even be necessary. Alternatively, you could add protect rules to your filter list for the directories that are genuinely empty on the source side. From the rsync man page:

You can prevent the pruning of certain empty directories from the file-list by using a global "protect" filter. For instance, this option would ensure that the directory "emptydir" was kept in the file-list:

--filter ’protect emptydir/’

The short name for protect is just a capital P, so for example the rule might look like

P .stfolder

to protect a syncthing .stfolder from being pruned.

Unless the folders you want to exclude or protect can be identified using a pattern you will need to be fairly explicit with your rules but some combination of these two approaches should be able to achieve what you want. In my experience, rsync rules are never quite finished but rather are gradually refined as the years go by.

Related Question