If a single file is specified for rsyncing, and that file is specified in the exclude file, it gets rsynced anyway. This is broken behaviour - if there is such a conflict of instruction, it should fail "safe" and do nothing. e.g.: $ cat /tmp/test/exclude /tmp/test/1/foo $ touch /tmp/test/1/foo $ ls -laR /tmp/test/ /tmp/test/: total 4 drwxrwxr-x 4 gordan gordan 100 May 21 22:22 . drwxrwxrwt 13 root root 280 May 21 22:31 .. drwxrwxr-x 2 gordan gordan 60 May 21 22:05 1 drwxrwxr-x 2 gordan gordan 40 May 21 22:23 2 -rw-rw-r-- 1 gordan gordan 16 May 21 22:22 exclude /tmp/test/1: total 4 drwxrwxr-x 2 gordan gordan 60 May 21 22:05 . drwxrwxr-x 4 gordan gordan 100 May 21 22:22 .. -rw-rw-r-- 1 gordan gordan 5 May 21 22:05 foo /tmp/test/2: total 0 drwxrwxr-x 2 gordan gordan 40 May 21 22:23 . drwxrwxr-x 4 gordan gordan 100 May 21 22:22 .. $ rsync --exclude-from=/tmp/test/exclude /tmp/test/1/foo /tmp/test/2/ $ ls -la /tmp/test/2/ total 4 drwxrwxr-x 2 gordan gordan 60 May 21 22:42 . drwxrwxr-x 4 gordan gordan 100 May 21 22:22 .. -rw-rw-r-- 1 gordan gordan 5 May 21 22:42 foo Tested on both x86 and x64, and rsync versions 2.6.8 and 3.0.7, so this seems to be a long standing issue.
Your exclude pattern is incorrect. Please see the "ANCHORING INCLUDE/EXCLUDE PATTERNS" section of the man page.
(In reply to comment #1) > Your exclude pattern is incorrect. Please see the "ANCHORING INCLUDE/EXCLUDE > PATTERNS" section of the man page. > Quote 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 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)." Can you explain how the pattern "/tmp/test/1/foo" doesn't match the file "/tmp/test/1/foo"? What should the correct pattern be?
Since you aren't using --relative, the "root of the transfer" is at the last slash in the source argument. The exclude pattern should be simply /foo .
Alternately, if you want to specify an absolute path, use a filter file with the slash (/) modifier. i.e., if you put this in your /tmp/test/exclude file: -/ /tmp/test/1/foo and use this command: rsync -aiv --filter='. /tmp/test/exclude' /tmp/test/1/foo /tmp/test/2/ then rsync will exclude that path at any point in any transfer. If --delete were added, keep in mind that the protected file on the receiving side must also match the absolute path, so no "foo" in the receiving directory would be protected from deletion in the above transfer (unlike using --exclude=/foo).