Different rsync behavior for identical directory name

rsync

I want to synchronize 2 codebases. The below command is working great, except that it doesn't account for one use case that I have with 2 directories named test in different locations:

  • /test/
  • /start/test/

$ rsync -avCz --delete-before --progress --exclude=test /tmp/codebase/ .

What I want to do is to exclude the /test directory completely from the rsync but I do want /start/test to be rsync'ed.

I'd prefer not to have to come up with a static TXT file that I should pass as an argument to rsync. Is there any way to achieve this otherwise? Playing with –include VS –exclude and a trailing slash (–exclude=test/) didn't work as anticipated for me.

Best Answer

You can use a leading / to match only in the root of the transfer. Try this:

rsync -avCz --delete-before --progress --exclude=/test/ /tmp/codebase/ .

Here is the man page snippet for the leading /:

if the pattern starts with a / then it is anchored to a particular spot in the hierarchy of files, otherwise it is matched against the end of the pathname. This is similar to a leading ^ in regular expressions. Thus "/foo" would match a name of "foo" at either the "root of the transfer" (for a global rule) or in the merge-file’s directory (for a per-directory rule). An unqualified "foo" would match a name of "foo" anywhere in the tree because the algorithm is applied recursively from the top down; it behaves as if each path component gets a turn at being the end of the filename. Even the unanchored "sub/foo" would match at any point in the hierarchy where a "foo" was found within a directory named "sub".

And for the trailing /:

if the pattern ends with a / then it will only match a directory, not a regular file, symlink, or device.

Update

I am guessing from you comments that you are also looking for the --delete-excluded option.

Related Question