How can I prevent a directory from being removed in rsync
Rsync is an awesome tool, but sometimes difficult to use.
The problem is you're using --exclude-from
, which sets global exclude rules to both the sending and receiving side.
Before rsync performs operations on the filesystem, it will first assemble two lists of files, one for the sending side (client) and other for the receiving side (server). If a file is excluded from both sides, rsync will simply ignore it. If it is excluded only from the sending side and exists on the receiving side, rsync will delete it.
In your case, since your rules are excluding files from both sides, rsync will not delete them. You then use --delete-excluded
to force deletion. But, like you said, this option conflicts with --backup --backup-dir=rsync/backup
.
I suggest you do the following.
- Convert
$EXCL_FROM
to a normal filter file, i.e., insert the minus sign before each line to make them exclude rules. - Remove
--exclude-from=$EXCL_FROM
and--delete-excluded
from the rsync options. - Include
-FF
on the rsync options. Include the following command before the call to rsync.
cp "$EXCL_FROM" "$SRC/.rsync-filter"
In this way, your rules will only apply to the sending side, and files specified as exclude rules will be removed from the receiving side if found. This should not conflict with backup options.
Update
Essentially, the -FF
option is making rsync process per-directory filter files named .rysnc-filter
in both sides of the transfer. In your case it will exist only on the sending side, so its rules won't apply to the receiving side.
Actually, -FF
equals to -F -F
. The first F
tells rsync to merge rules from .rsync-filter
in the root of the source and destination directories, like I said before. The second F
tells rsync to exclude them. You don't want .rsync-filter
being transferred, otherwise your exclude rules would also apply to the receiving side and your original problem would return – the excluded files would cease to be deleted.
Here's what my man (1) rsync
says:
-F same as --filter='dir-merge /.rsync-filter' repeated: --filter='- .rsync-filter'
One alternative is to locate your --backup-dir
outside of your backup folder using absolute paths (specified with ../
).
ie. --backup-dir="../rsync/backup/${DATE}"
This will create a new folder at the same level as your destination folder. For example, if you were exporting to /home/user/rsync/backup
the above command would store your deleted files at home/user/rsync/rsync/backup/${DATE}