rsync --filter: Per-Directory and Merge Rules
rsync --filter is the general rule syntax behind --include and --exclude, plus protect, hide, and per-directory merge rules.
When a deploy needs to keep certain server files safe from --delete, or wants per-directory rules checked into the repo, --filter is the tool.
What it does
Each --filter rule starts with a short prefix: "+ " include, "- " exclude, "P " protect (keep on the destination even with --delete), "H " hide, and ":" or "." for merge files. Like include/exclude, rules are first-match-wins in order.
Common usage
# Protect server-side uploads from --delete
rsync -av --delete --filter='P uploads/***' dist/ user@host:/var/www/app/
# Merge per-directory rules from .rsync-filter files
rsync -av --filter=': /.rsync-filter' src/ user@host:/srv/Filter rule prefixes
| Prefix | Meaning |
|---|---|
| + pattern | Include matching files |
| - pattern | Exclude matching files |
| P pattern | Protect from deletion on the destination |
| H pattern | Hide from the sending side |
| : name | Per-directory merge file (dir-merge) |
| . file | Merge rules from a file once |
In CI
Protect rules let you mirror code with --delete while leaving runtime data (user uploads, generated caches) untouched on the server. The "***" wildcard matches everything below a directory including the directory itself, which is what you usually want for a protect rule.
Common errors in CI
A merge file rule like ": /.rsync-filter" that points at a missing file is silently ignored, so deletions you expected to be protected can happen anyway. Verify with --dry-run --delete that protected paths show no "deleting" lines before running for real.