What you want to do is reasonable, but using rsync
to do it on its own is not. So the answer is no.
The reason is simple: rsync
keeps no history of what was in each directory and has no way of knowing what needs to be deleted and what not. Not without additional support.
You should ask yourself why you like to do this with rsync
and make that more clear. There are other programs that use librsync1.so
that are more intelligent.
With the relaxed constraints that you don't need
rsync
per se, you can take a look at
rdiff-backup:
mkdir a
touch a/xx
touch a/yy
rdiff-backup a b
ls b
This shows xx
and yy
are in b
.
touch b/zz
rm a/xx
rdiff-backup a b
This shows xx
and zz
are in b
. rdiff-backup
also keeps a directory rdiff-backup-data
in b
so you can rollback any changes, you should purge this on a regular basis using the rdiff-backup
commands. (The example is with local files to show extra data in the target does not get deleted, but rdiff-backup works over a network as well).
Another alternative is to setup some distributed revision control system (mercurial, bazaar, git). With mercurial e.g. you can have a script (I use a Makefile for that), that pushes all the changes to the server and then does an update of the checked out files there, ignore any additional files that are on the remote server (but have not been put under revision control).
On the server you would do:
hg init
hg add file_list_excluding_that_should_not_should_be_deleted_if_not_on_client
hg commit -m "initial setup"
On the client:
hg clone ssh://username@server/dir_to_repository
Now if you remove a file on the client and do:
hg commit -m "removed file"
ssh username@server "cd dir_to_repository; hg update --clean"
Your removed file is removed on the server, but any other data (not added to the repository) does not get deleted.
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.
Best Answer
You've included
/models
in the traversal, but none of its subdirectories. If a directory is excluded, rsync doesn't traverse it, so none of its contents can be included.Use
--include='*/'
to include all subdirectories, and-m
to not copy directories that would end up empty. For more information, see Rsync filter: copying one pattern only