Cannot get rsync exclude option to exclude dir

mkdir -p test/a/b/c/d/e
mkdir -p test/dest
rsync -nvraL test/a test/dest --exclude=a/b/c/d 

This works. As test/a is the base directory synced from, the exclude pattern is specified by starting with a/

Show us the real paths/excludes if this doesn't help.

Running rsync with -vn will list dirs/files - the pattern is matched against the format that rsync prints.


Either of these would work:

rsync -nvraL test/a test/dest --exclude=/a/b/c/d
rsync -nvraL test/a/ test/dest --exclude=/b/c/d

Note the ending / in source path makes a critical difference to how --exclude should be specified. This assumes we have:

mkdir -p test/a/b/c/d/e
mkdir -p test/a/other/place/a/b/c/d
mkdir -p test/dest

Original Post has difficulty when exclude path starts with a /. Daniel’s answer is correct that this initial / in exclude path might be desirable to exclude a specific path, and that this initial / should be understood like leading ^ in regular expressions. However, his answer has a critical typo about the ending / in source path.


Following Erik's example you want to do this:

rsync -nvraL test/a/ test/dest --exclude=/b/c/d

Actually, neither Erik's nor Antoni's answer is fully accurate.

Erik is halfway right in saying that

As test/a is the base directory synced from, the exclude pattern is specified by starting with a/

It is true that the exclude pattern's root is test/a (i.e. the pattern /some/path binds to test/a/some/path), but that's not the whole story.

From the man page:

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 file named "foo" at either the "root of the transfer" (for a global rule) or in the merge-file's directory (for a per-directory rule).

We can ignore the per-directory bit as it doesn't apply to us here.

Therefore, rsync -nvraL test/a test/dest --exclude=a/b/c/d will most definitely exclude test/a/b/c/d (and children), but it'll also exclude test/a/other/place/a/b/c/d.

rsync -nvraL test/a test/dest --exclude=/b/c/d, on the other hand, will exclude only test/a/b/c/d (and children) (test/a being the point to which / is anchored).

This is why you still need the anchoring inital slash if you want to exclude that specific path from being backed up. This might seem like a minor detail, and it will be so the more specific your exclude pattern becomes (e.g. Pictures vs. home/daniel/Pictures) but it might just come around to bite you in the butt.