An rsync filter rule can hide a parent directory before a later include rule ever evaluates the file expected in the transfer. A dry run with filter debugging shows whether each path is being hidden or shown, and which pattern made that decision, before a live sync changes the destination.
Rsync applies include, exclude, and filter rules while building the file list. A file-level include cannot rescue a path if rsync never descends into its parent directory, so parent-directory includes, specific excludes, and final catch-all excludes need to be tested in the same order the real command uses.
Run the debug pass against a controlled copy of the command or a disposable test tree whenever possible. For local copies and pushes, –debug=FILTER is enough; for remote pulls, pass the option to the remote sender with -M–debug=FILTER so the side deciding what to send reports the rule matches.
$ rsync -av --dry-run --debug=FILTER --include='documents/report.txt' --exclude='*' /tmp/source/ /tmp/dest/ sending incremental file list [sender] hiding directory logs because of pattern * [sender] hiding directory documents because of pattern * sent 51 bytes received 12 bytes 126.00 bytes/sec total size is 0 speedup is 0.00 (DRY RUN)
The sample is intentionally missing an include rule for documents/, so rsync cannot descend far enough to evaluate documents/report.txt.
In the sample output, documents is hidden by the final * pattern. Because rsync does not descend into that directory, documents/report.txt is never evaluated.
$ rsync -av --dry-run --debug=FILTER --include='documents/' --include='documents/report.txt' --exclude='*' /tmp/source/ /tmp/dest/ sending incremental file list [sender] hiding directory logs because of pattern * [sender] showing directory documents because of pattern documents/ [sender] hiding file documents/draft.tmp because of pattern * [sender] showing file documents/report.txt because of pattern documents/report.txt documents/ documents/report.txt sent 121 bytes received 19 bytes 280.00 bytes/sec total size is 6 speedup is 0.04 (DRY RUN)
Directory include rules normally need a trailing slash, such as documents/, so they match the directory itself instead of a same-named file.
$ rsync -av --dry-run --debug=FILTER --include='documents/' --include='documents/report.txt' --exclude='*.tmp' --exclude='*' /tmp/source/ /tmp/dest/ sending incremental file list [sender] hiding directory logs because of pattern * [sender] showing directory documents because of pattern documents/ [sender] hiding file documents/draft.tmp because of pattern *.tmp [sender] showing file documents/report.txt because of pattern documents/report.txt documents/ documents/report.txt sent 121 bytes received 19 bytes 280.00 bytes/sec total size is 6 speedup is 0.04 (DRY RUN)
–include and –exclude are shorthand filter rules. Keep any existing –filter, –include-from, or –exclude-from inputs in the same relative order when adding the debug flags.
$ rsync -av --dry-run -M--debug=FILTER host:/src/ /dest/
Modern rsync does not automatically forward non-default debug flags to the remote side, so -M–debug=FILTER asks the sender to report filter decisions during a pull.
Remove –dry-run only after the filter output has been reviewed; a live command with –delete can remove destination-only files that the filters no longer protect.