I am running Fedora 17 64-bit and the rsync --exclude=/home/ben/<dir> is not working as expected.

I am trying to rsync my home directory to a thumb drive, but I want to exclude certainly directories that hold cache files and build files. This is the command I'm using:

rsync --exclude=/home/ben/build/ --exclude=/home/ben/.ccache -arv /home/ben home-ben/

However, content from the ~/build and ~/.ccache is being copied by rsync. What am I doing wrong?

  • 2
    I think exclude patterns just don't work. – Sören Sep 27 '18 at 18:53

Global rsync filter rules beginning with a leading / are anchored to the root of transfer. Quoting from the "INCLUDE/EXCLUDE PATTERN RULES" section of 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).

In your command (rsync ... -arv /home/ben home-ben/), the file /home/ben/foo would be transferred to home-ben/ben/foo. The root of transfer is home-ben and the correct filter path is /ben/foo. Thus,

  • to match /home/ben/.ccache you need a filter path of /ben/.ccache
  • to match /home/ben/build/ you need a filter path of /ben/build/

A more detailed explanation can be found in the "ANCHORING INCLUDE/EXCLUDE PATTERNS" section of the rsync(1) man page.

Note that simply leaving out the leading / is not necessarily what you want. Quoting again from the same man page section:

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". See the section on ANCHORING INCLUDE/EXCLUDE PATTERNS for a full discussion of how to specify a pattern that matches at the root of the transfer.

Thus a filter pattern of build/ would match a build directory anywhere in /home/ben, even /home/ben/many/sub/directories/build/.

| improve this answer | |
  • 4
    The key detail is that slashes matter. If you append a slash to the end of the source directory (rsync -a source/ destination) it will copy the contents of source, otherwise rsync -a source destination copies the source directory itself to the destination. This determines what the root of the transfer will be in order to inform the exclude expression. The proper use of / in the exclude expression is then explained above. Note in particular that rsync --exclude='/dir1' source destination won't exclude anything. – pgoetz Jun 19 '15 at 13:38

Per @rubo77's comment below, this answer should only be used if you're willing to exclude these items everywhere in your source tree, not just at the root. See @jw013's answer above for a more thorough explanation.

I think your exclude paths need to be relative to the source path. Can you try this instead?

rsync --exclude=build/ --exclude=.ccache -arv /home/ben home-ben/

Here's a test, for comparison:

/tmp$ tree src dest
├── a
└── b
└── foo/

/tmp$ rsync -nav --exclude /tmp/src/b /tmp/src /tmp/dest
sending incremental file list

$ rsync -nav --exclude b /tmp/src /tmp/dest
sending incremental file list
| improve this answer | |
  • 3
    This answer is wrong. With a relative exclude path you would exclude the pattern everywhere! – rubo77 Feb 4 '18 at 5:07
  • This post is correct. The matching is text-based, not file inode-based. Whatever path the output of the --verbose command shows is the format you have to use. – Sridhar Sarnobat May 1 '18 at 21:34
  • This worked for me. – Zhenyu May 28 '18 at 11:57
  • What if the source path is '/' then absolute are the relative paths, but it still doesn't work. – Sören Sep 27 '18 at 18:51
  • 1
    This is the only thing that worked for me. – Jonathan Aug 30 '19 at 9:46

Your exclude pattern would work, if you rsync the whole /home path i.e. without a trailing slash:

rsync --exclude=/home/ben/build/ --exclude=/home/ben/.ccache -arv /home home-all/

But better only rsync the content of the folder with a trailing slash:

rsync --exclude=/build --exclude=/.ccache -arv /home/ben/ home-ben/

You can use an ignore-list too, see: https://askubuntu.com/questions/545655/backup-your-home-directory-with-rsync-and-skip-useless-folders

| improve this answer | |

I had this problem in a script (I don't know if it's your case). I was because I used this command in a script and I was using sh instead of bash. check the shebang at the beginning of your script.

| improve this answer | |
  • 1
    How would the shell choice of shell interpreter cause this particular issue? – Kusalananda May 25 at 14:43

In order to exclude a specif folder with rsync you need consider the relative path in the command. in you case:

rsync --exclude=/ben/build/ --exclude=/ben/.ccache -arv /home/ben home-ben/

where "ben" is the folder you are syncing

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.