I do the following:

rsync --recursive --delete --delete-excluded --exclude-from=$HOME/etc/rsync_exclude.txt --relative --safe-links --executability . /path/to/savedir

Note that the source directory is the working directory (specified as .)

Inside the working directory, I have a directory ./repository and a file ./Vagrantfile.

The file rsync_exclude.txt contains, among others, the lines


I would have expected that these entries would exceed my repository and Vagrantfile, because

  • the leading slash expresses that the names are to be anchored at the root directory for saving, which is the working directory, and
  • the trailing slash on repository explicitly states that this is a directory, not a file

However, both entries are copied.

What did I do wrong?

(This is rsync 2.6.9 running on MacOS Sierra (but I don't think this matters in this case)).


When debugging rsync (using -vv and --dry-run) I can clearly see that all non-anchored rules are accepted (for instance, rsync tells me hiding directory vp5/.git because of pattern .git/), but none of the anchored rules work. I also tried to replace the source directory (.) by ./ or $PWD, but this too did not have any effect.

Furthermore, when I remove the leading / (for instance, turning /repository/ into repository/), the directory is excluded. Of course this directory would now be excluded anywhere in the tree, which doesn't harm in this particular case, but is not what I want in general).

  • Does this change if you use ./ in place of .?
    – Kusalananda
    May 2 '17 at 14:29
  • You might get some hints on how your filter works with --debug=FILTER2
    – meuh
    May 2 '17 at 16:53
  • This should work. Run rsync -vv … to see what decisions it makes. Check that your file doesn't have any stray whitespace or invisible characters, such as carriage returns (Windows line endings don't work outside Windows). May 2 '17 at 21:58
  • 1
    --relative doesn't really add value if your source directory is .. You might want to include --times or even --archive in your set of options so that rsync can more easily detect that a file doesn't need to be recopied.
    – roaima
    May 2 '17 at 22:26
  • 1
    I suggest you create a small example that is modeled from your real case and that you post the output of the entire transaction here. With vague hints about what happened you won't get much beyond hand-waving. May 3 '17 at 10:02

The following works for me with rsync version 3.1.2:

$ ls -F
archive/  backup/  mk-archive.sh*  mk-backup.sh*  mk-cloud.sh*  mk-source.sh*  source/

$ cat /tmp/excludes

$ mkdir -p /tmp/target
$ rsync --relative --recursive --delete --delete-excluded --exclude-from=/tmp/excludes . /tmp/target/

$ ls -F /tmp/target
mk-cloud.sh*  mk-source.sh*  source/

What's happening here is as described in the man page for rsync, so your patterns must be anchored to / immediately at the start of the copy (i.e. under .).

As mentioned earlier, global include/exclude patterns are anchored at the "root of the transfer" [...].

Because the matching is relative to the transfer-root, changing the trailing slash on a source path or changing your use of the --relative option affects the path you need to use in your matching (in addition to changing how much of the file tree is duplicated on the destination host). [...]


cd /home; rsync -a --relative me/foo you/ /dest

+/- pattern: /me/foo/bar (starts at specified path)
+/- pattern: /you/bar/baz (ditto)

Target file: /dest/me/foo/bar
Target file: /dest/you/bar/baz

You can see the exclusions being acted upon by adding -vv (or --verbose --verbose) to the rsync command.

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.