256

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
  • 9,212
  • 8
    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

329

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,121
Freedom_Ben
  • 9,212
  • 10
    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
  • 15
    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
151

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
  • 123
user228759
  • 1,511
  • 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
134

You can also exclude multiple paths within curly braces:

rsync -arv --exclude={.ccache,build} /home/ben /media/ben/thumbdrive/
  • 56
    this works nicely, just not under sh, only under bash, I found out "the hard way" – Frido Emans Oct 01 '15 at 09:56
  • 24
    No space after the comma. Learnt that the hard way too – Jerry U May 25 '18 at 05:21
  • 2
    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
  • 4
    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
  • 6
    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