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.