Skip to content

Including and Excluding

Scope: telling rsync to skip parts of the tree — cache directories, scratch files, VCS internals — and the pattern rules that decide what a rule hits.

One pattern, one run

--exclude='PATTERN' skips anything matching. The lab tree holds a site with caches at two depths, logs, a .git directory, and scratch files:

exsrc/
  index.html        style.css
  cache/top.html            <- cache at the top
  assets/logo.png
  assets/cache/deep.html    <- cache, nested
  logs/app.log
  .git/config
  scratch.tmp       notes.tmp

One unanchored pattern:

rsync -a --exclude='cache' exsrc/ exdest1/

Result: both cache directories are gone — top and nested. A pattern with no slash in it matches the name at any depth. That is usually what you want for caches, node_modules, and build output: wherever they appear, they are excluded.

Anchoring: the leading slash

Put a slash at the front and the pattern is anchored to the root of the transfer — it only matches at that level:

rsync -a --exclude='/cache' exsrc/ exdest2/

Result: the top-level cache/ is gone, but assets/cache/deep.html arrived. Same word, different rule. A pattern containing a slash anywhere except the very end is likewise anchored; a trailing slash (logs/) restricts the match to directories. And * in a pattern does not cross a / — assets/* and assets/** are different rules (documented); reach for ** when a pattern must span directories.

Check: after any exclude run, find destination -type f | sort against the source listing. Excludes fail silently — nothing reports what didn't travel — so the only proof is the listing.

Pattern files: --exclude-from

More than a couple of rules belong in a file, one pattern per line, reusable across commands:

$ cat patterns.txt
*.tmp
.git/
logs/

$ rsync -a --exclude-from=patterns.txt exsrc/ exdest3/

Every .tmp file, the .git directory, and logs/ stayed home; the rest of the tree — including both caches, which this rule set doesn't mention — synced. Blank lines and lines starting with # or ; are comments. The file itself is in examples/ (as exclude-patterns.txt), alongside the command set in recipes.txt.

--include exists for the exceptions: rules are evaluated in order, first match wins, so --include='keep.tmp' --exclude='*.tmp' rescues one file from a broad exclusion (documented). Order your rules from the specific to the general, and remember a directory must be included before rsync will descend into it to include anything inside.

The other direction: --files-from

Sometimes the list of what you want is shorter than the list of what you don't. --files-from names the files to transfer, one per line, and rsync takes exactly those:

$ cat list.txt
index.html
assets/logo.png

$ rsync -a --files-from=list.txt exsrc/ exdest4/
$ find exdest4 -type f | sort
exdest4/assets/logo.png
exdest4/index.html

Parent directories are created as needed; everything not listed is ignored, however much of it there is. It is the right shape for manifests, deploy lists, and "these twelve files, to that server" jobs — the list can be generated by another tool, which is where this option quietly becomes powerful.