248

I am trying to backup my home directory using rsync, and I want to exclude some of the directories that contain junk. I want to specifically exclude /home/ben/.ccache and /home/ben/build. Unfortunately the documentation for rsync was information overload and didn't answer my question. This is what I tried:

rsync -arv --exclude "/home/ben/.ccache:/home/ben/build" /home/ben /media/ben/thumbdrive/

What is the right way to do this?

Freedom_Ben
  • 8,942
  • 7
  • 26
  • 36
  • 7
    Just wanted to say that the flag `a` implies `r` already :) `-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)` – Populus Apr 17 '15 at 13:32

3 Answers3

319

To exclude multiple directories you just use multiple --exclude=path switches. So the command from the question properly written is as follows:

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

Note: Use relative paths with exclude. The paths are relative to the source directory, here /home/ben.

mit
  • 2,081
  • 4
  • 19
  • 23
Freedom_Ben
  • 8,942
  • 7
  • 26
  • 36
  • 9
    An absolute path did *not* work for me (the directory specified was silently not excluded), whereas a path relative to the source directory worked correctly. Maybe I'm missing something, but I would be cautious about @FreeSoftwareServers' assertion that absolute paths always work. – Soren Bjornstad Aug 20 '16 at 19:43
  • 1
    FWIW, a little creative *diff* use can be helpful. Assume you are adjusting the exclude flags from run to run in **nas_backup.sh**. Assume also that are using `--dry-run`. run: `. nas_backup.sh > dryrun.5.txt`, adjust excludes, then run `. nas_backup.sh > dryrun.6.txt` then diff `diff dryrun.5.txt dryrun.6.txt | less` this will show you what was added/removed from scope between those 2 runs. – JL Peyret May 04 '17 at 20:17
  • 14
    FYI: The option `-a` includes `-r` so `-ar` is redundant. – David Aug 08 '17 at 14:01
  • 10
    Contrary to what FreeSoftwareServers believes, the exclude path is relative to the source path, NOT /. So that comment is categorically false and will lead to failures if you follow it. The best strategy is to leave off the leading / in your excludes to avoid this type of mental error. If source is say, /home/me and if you exclude='/mydir/' this excludes the directory mydir in /home/me, that is, it excludes /home/me/mydir NOT /mydir/ at /. It's unfortunate I can't either downvote or edit that comment since it's technically wrong and will mislead. – Lizardx Sep 06 '17 at 00:09
  • 1
    http://www.thegeekstuff.com/2011/01/rsync-exclude-files-and-folders/?utm_source=feedburner explains this quite clearly, note the section: 4. Exclude path is always relative (to the source path) – Lizardx Sep 06 '17 at 00:13
  • 6
    FYI for later travellers, it looks like the comment in question by @FreeSoftwareServer has been removed. tl;dr: use relative paths – Freedom_Ben Sep 06 '17 at 16:25
  • 3
    If you're dumb then so am I and 179 other upvoters! – Sridhar Sarnobat Sep 22 '18 at 04:48
  • @Soren Bjornstad: you're right, it doesn't exclude the directory if you specify an absolute path. It has to be a relative path to the source directory for it to work. – John Smith Optional May 09 '19 at 15:28
  • Hm, is it possible at all to find this in the man page? That one can use the parameter several times? – robsch Nov 19 '20 at 15:01
  • Wow, I think this really trapped me and still puzzles me: it seems that you really need to put an equal sign `=` if you want to specify more than one exclude directory. – Matthias W. Nov 28 '21 at 22:38
148

When having multiple directories and/or files to exclude, make a text file and use the --exclude-from switch. Make a file called exclude_me.txt and in it list your exclusions. Example (/home/ben/exclude_me.txt):

.ccache
build
.java
.gvfs
.xsession-errors

Then your rsync would look something like this:

rsync -arv --exclude-from='/home/ben/exclude_me.txt' /home/ben /media/ben/thumbdrive/

This is some information on filter rules that may help:

  • /dir/ means exclude the root folder /dir
  • /dir/* means get the root folder /dir but not the contents
  • dir/ means exclude any folder anywhere where the name contains dir/

  • Examples excluded: /dir/, /usr/share/directory/, /var/spool/dir/ /var/spool/lpd/cf means skip files that start with cf within any folder within /var/spool/lpd

Also see the filter rules section on the man page.

mbomb007
  • 103
  • 5
user228759
  • 1,481
  • 1
  • 9
  • 3
  • 13
    It's important to note that *root folder* means the *root of the transfer* not the root directory. – jamesdlin Sep 10 '18 at 20:12
  • `/var/spool/lpd/cf` excludes only the filename `cf`. To exclude all filenames starting with `cf`, you need to use `/var/spool/lpd/cf*`. And note: `/var/spool/lpd/cf` even excludes the dir name `cf` in this subdir. – mgutt Mar 08 '22 at 05:37
128

You can also exclude multiple paths within curly braces:

rsync -arv --exclude={.ccache,build} /home/ben /media/ben/thumbdrive/
György Ráth
  • 1,281
  • 1
  • 8
  • 2
  • 54
    this works nicely, just not under sh, only under bash, I found out "the hard way" – Frido Emans Oct 01 '15 at 09:56
  • 22
    No space after the comma. Learnt that the hard way too – Jerry U May 25 '18 at 05:21
  • 1
    And don't use '' like --exclude='.gvfs' – Martin T. Nov 21 '18 at 09:03
  • FWIW, I think curly braces work with ksh. For other shells, you could probably use something like: `IFS=$'\n'; rsync -arv $(printf '.ccache\nbuild\n' | sed 's/^/--exclude=/g') /home/ben /media/ben/thumbdrive/`. Or, you could just use multiple `--exclude` arguments, which you'd have to type manually. – TSJNachos117 Jan 24 '19 at 00:27
  • 3
    The reason this works is because of "Brace Expansion", in case anyone wanted to look at the details. – shredalert Jun 05 '19 at 12:50
  • 5
    It also works to have brace expansion in the middle of a path, like `--exclude=/folder/{one,two}/*` – mbomb007 Sep 10 '19 at 21:03