+Rsync builds an ordered list of filter rules as specified on the
+command-line. Filter rules have the following syntax:
+
+quote(
+tt(RULE [PATTERN_OR_FILENAME])nl()
+tt(RULE,MODIFIERS [PATTERN_OR_FILENAME])nl()
+)
+
+You have your choice of using either short or long RULE names, as described
+below. If you use a short-named rule, the ',' separating the RULE from the
+MODIFIERS is optional. The PATTERN or FILENAME that follows (when present)
+must come after either a single space or an underscore (_).
+Here are the available rule prefixes:
+
+quote(
+bf(exclude, -) specifies an exclude pattern. nl()
+bf(include, +) specifies an include pattern. nl()
+bf(merge, .) specifies a merge-file to read for more rules. nl()
+bf(dir-merge, :) specifies a per-directory merge-file. nl()
+bf(hide, H) specifies a pattern for hiding files from the transfer. nl()
+bf(show, S) files that match the pattern are not hidden. nl()
+bf(protect, P) specifies a pattern for protecting files from deletion. nl()
+bf(risk, R) files that match the pattern are not protected. nl()
+bf(clear, !) clears the current include/exclude list (takes no arg) nl()
+)
+
+When rules are being read from a file, empty lines are ignored, as are
+comment lines that start with a "#".
+
+Note that the bf(--include)/bf(--exclude) command-line options do not allow the
+full range of rule parsing as described above -- they only allow the
+specification of include/exclude patterns plus a "!" token to clear the
+list (and the normal comment parsing when rules are read from a file).
+If a pattern
+does not begin with "- " (dash, space) or "+ " (plus, space), then the
+rule will be interpreted as if "+ " (for an include option) or "- " (for
+an exclude option) were prefixed to the string. A bf(--filter) option, on
+the other hand, must always contain either a short or long rule name at the
+start of the rule.
+
+Note also that the bf(--filter), bf(--include), and bf(--exclude) options take one
+rule/pattern each. To add multiple ones, you can repeat the options on
+the command-line, use the merge-file syntax of the bf(--filter) option, or
+the bf(--include-from)/bf(--exclude-from) options.
+
+manpagesection(INCLUDE/EXCLUDE PATTERN RULES)
+
+You can include and exclude files by specifying patterns using the "+",
+"-", etc. filter rules (as introduced in the FILTER RULES section above).
+The include/exclude rules each specify a pattern that is matched against
+the names of the files that are going to be transferred. These patterns
+can take several forms:
+
+itemization(
+ it() if the pattern starts with a / then it is anchored to a
+ particular spot in the hierarchy of files, otherwise it is matched
+ against the end of the pathname. This is similar to a leading ^ in
+ regular expressions.
+ Thus "/foo" would match a file named "foo" at either the "root of the
+ transfer" (for a global rule) or in the merge-file's directory (for a
+ per-directory rule).
+ An unqualified "foo" would match any file or directory named "foo"
+ anywhere in the tree because the algorithm is applied recursively from
+ the
+ top down; it behaves as if each path component gets a turn at being the
+ end of the file name. Even the unanchored "sub/foo" would match at
+ any point in the hierarchy where a "foo" was found within a directory
+ named "sub". See the section on ANCHORING INCLUDE/EXCLUDE PATTERNS for
+ a full discussion of how to specify a pattern that matches at the root
+ of the transfer.
+ it() if the pattern ends with a / then it will only match a
+ directory, not a file, link, or device.
+ it() rsync chooses between doing a simple string match and wildcard
+ matching by checking if the pattern contains one of these three wildcard
+ characters: '*', '?', and '[' .
+ it() a '*' matches any non-empty path component (it stops at slashes).
+ it() use '**' to match anything, including slashes.
+ it() a '?' matches any character except a slash (/).
+ it() a '[' introduces a character class, such as [a-z] or [[:alpha:]].
+ it() in a wildcard pattern, a backslash can be used to escape a wildcard
+ character, but it is matched literally when no wildcards are present.
+ it() if the pattern contains a / (not counting a trailing /) or a "**",
+ then it is matched against the full pathname, including any leading
+ directories. If the pattern doesn't contain a / or a "**", then it is
+ matched only against the final component of the filename.
+ (Remember that the algorithm is applied recursively so "full filename"
+ can actually be any portion of a path from the starting directory on
+ down.)
+ it() a trailing "dir_name/***" will match both the directory (as if
+ "dir_name/" had been specified) and all the files in the directory
+ (as if "dir_name/**" had been specified). This behavior was added in
+ version 2.6.7.
+)
+
+Note that, when using the bf(--recursive) (bf(-r)) option (which is implied by
+bf(-a)), every subcomponent of every path is visited from the top down, so
+include/exclude patterns get applied recursively to each subcomponent's
+full name (e.g. to include "/foo/bar/baz" the subcomponents "/foo" and
+"/foo/bar" must not be excluded).
+The exclude patterns actually short-circuit the directory traversal stage
+when rsync finds the files to send. If a pattern excludes a particular
+parent directory, it can render a deeper include pattern ineffectual
+because rsync did not descend through that excluded section of the
+hierarchy. This is particularly important when using a trailing '*' rule.
+For instance, this won't work:
+
+quote(
+tt(+ /some/path/this-file-will-not-be-found)nl()
+tt(+ /file-is-included)nl()
+tt(- *)nl()
+)
+
+This fails because the parent directory "some" is excluded by the '*'
+rule, so rsync never visits any of the files in the "some" or "some/path"
+directories. One solution is to ask for all directories in the hierarchy
+to be included by using a single rule: "+ */" (put it somewhere before the
+"- *" rule), and perhaps use the bf(--prune-empty-dirs) option. Another
+solution is to add specific include rules for all
+the parent dirs that need to be visited. For instance, this set of rules
+works fine:
+
+quote(
+tt(+ /some/)nl()
+tt(+ /some/path/)nl()
+tt(+ /some/path/this-file-is-found)nl()
+tt(+ /file-also-included)nl()
+tt(- *)nl()
+)
+
+Here are some examples of exclude/include matching:
+
+itemization(
+ it() "- *.o" would exclude all filenames matching *.o
+ it() "- /foo" would exclude a file (or directory) named foo in the
+ transfer-root directory
+ it() "- foo/" would exclude any directory named foo
+ it() "- /foo/*/bar" would exclude any file named bar which is at two
+ levels below a directory named foo in the transfer-root directory
+ it() "- /foo/**/bar" would exclude any file named bar two
+ or more levels below a directory named foo in the transfer-root directory
+ it() The combination of "+ */", "+ *.c", and "- *" would include all
+ directories and C source files but nothing else (see also the
+ bf(--prune-empty-dirs) option)
+ it() The combination of "+ foo/", "+ foo/bar.c", and "- *" would include
+ only the foo directory and foo/bar.c (the foo directory must be
+ explicitly included or it would be excluded by the "*")
+)
+
+manpagesection(MERGE-FILE FILTER RULES)
+
+You can merge whole files into your filter rules by specifying either a
+merge (.) or a dir-merge (:) filter rule (as introduced in the FILTER RULES
+section above).
+
+There are two kinds of merged files -- single-instance ('.') and
+per-directory (':'). A single-instance merge file is read one time, and
+its rules are incorporated into the filter list in the place of the "."
+rule. For per-directory merge files, rsync will scan every directory that
+it traverses for the named file, merging its contents when the file exists
+into the current list of inherited rules. These per-directory rule files
+must be created on the sending side because it is the sending side that is
+being scanned for the available files to transfer. These rule files may
+also need to be transferred to the receiving side if you want them to
+affect what files don't get deleted (see PER-DIRECTORY RULES AND DELETE
+below).
+
+Some examples:
+
+quote(
+tt(merge /etc/rsync/default.rules)nl()
+tt(. /etc/rsync/default.rules)nl()
+tt(dir-merge .per-dir-filter)nl()
+tt(dir-merge,n- .non-inherited-per-dir-excludes)nl()
+tt(:n- .non-inherited-per-dir-excludes)nl()
+)
+
+The following modifiers are accepted after a merge or dir-merge rule:
+
+itemization(
+ it() A bf(-) specifies that the file should consist of only exclude
+ patterns, with no other rule-parsing except for in-file comments.
+ it() A bf(+) specifies that the file should consist of only include
+ patterns, with no other rule-parsing except for in-file comments.
+ it() A bf(C) is a way to specify that the file should be read in a
+ CVS-compatible manner. This turns on 'n', 'w', and '-', but also
+ allows the list-clearing token (!) to be specified. If no filename is
+ provided, ".cvsignore" is assumed.
+ it() A bf(e) will exclude the merge-file name from the transfer; e.g.
+ "dir-merge,e .rules" is like "dir-merge .rules" and "- .rules".
+ it() An bf(n) specifies that the rules are not inherited by subdirectories.
+ it() A bf(w) specifies that the rules are word-split on whitespace instead
+ of the normal line-splitting. This also turns off comments. Note: the
+ space that separates the prefix from the rule is treated specially, so
+ "- foo + bar" is parsed as two rules (assuming that prefix-parsing wasn't
+ also disabled).
+ it() You may also specify any of the modifiers for the "+" or "-" rules
+ (below) in order to have the rules that are read in from the file
+ default to having that modifier set. For instance, "merge,-/ .excl" would
+ treat the contents of .excl as absolute-path excludes,
+ while "dir-merge,s .filt" and ":sC" would each make all their
+ per-directory rules apply only on the sending side.
+)
+
+The following modifiers are accepted after a "+" or "-":
+
+itemization(
+ it() A bf(/) specifies that the include/exclude rule should be matched
+ against the absolute pathname of the current item. For example,
+ "-/ /etc/passwd" would exclude the passwd file any time the transfer
+ was sending files from the "/etc" directory, and "-/ subdir/foo"
+ would always exclude "foo" when it is in a dir named "subdir", even
+ if "foo" is at the root of the current transfer.
+ it() A bf(!) specifies that the include/exclude should take effect if
+ the pattern fails to match. For instance, "-! */" would exclude all
+ non-directories.
+ it() A bf(C) is used to indicate that all the global CVS-exclude rules
+ should be inserted as excludes in place of the "-C". No arg should
+ follow.
+ it() An bf(s) is used to indicate that the rule applies to the sending
+ side. When a rule affects the sending side, it prevents files from
+ being transferred. The default is for a rule to affect both sides
+ unless bf(--delete-excluded) was specified, in which case default rules
+ become sender-side only. See also the hide (H) and show (S) rules,
+ which are an alternate way to specify sending-side includes/excludes.
+ it() An bf(r) is used to indicate that the rule applies to the receiving
+ side. When a rule affects the receiving side, it prevents files from
+ being deleted. See the bf(s) modifier for more info. See also the
+ protect (P) and risk (R) rules, which are an alternate way to
+ specify receiver-side includes/excludes.
+ it() A bf(p) indicates that a rule is perishable, meaning that it is
+ ignored in directories that are being deleted. For instance, the bf(-C)
+ option's default rules that exclude things like "CVS" and "*.o" are
+ marked as perishable, and will not prevent a directory that was removed
+ on the source from being deleted on the destination.
+)
+
+Per-directory rules are inherited in all subdirectories of the directory
+where the merge-file was found unless the 'n' modifier was used. Each
+subdirectory's rules are prefixed to the inherited per-directory rules
+from its parents, which gives the newest rules a higher priority than the
+inherited rules. The entire set of dir-merge rules are grouped together in
+the spot where the merge-file was specified, so it is possible to override
+dir-merge rules via a rule that got specified earlier in the list of global
+rules. When the list-clearing rule ("!") is read from a per-directory
+file, it only clears the inherited rules for the current merge file.
+
+Another way to prevent a single rule from a dir-merge file from being inherited is to
+anchor it with a leading slash. Anchored rules in a per-directory
+merge-file are relative to the merge-file's directory, so a pattern "/foo"
+would only match the file "foo" in the directory where the dir-merge filter
+file was found.
+
+Here's an example filter file which you'd specify via bf(--filter=". file":)
+
+quote(
+tt(merge /home/user/.global-filter)nl()
+tt(- *.gz)nl()
+tt(dir-merge .rules)nl()
+tt(+ *.[ch])nl()
+tt(- *.o)nl()
+)
+
+This will merge the contents of the /home/user/.global-filter file at the
+start of the list and also turns the ".rules" filename into a per-directory
+filter file. All rules read in prior to the start of the directory scan
+follow the global anchoring rules (i.e. a leading slash matches at the root
+of the transfer).
+
+If a per-directory merge-file is specified with a path that is a parent
+directory of the first transfer directory, rsync will scan all the parent
+dirs from that starting point to the transfer directory for the indicated
+per-directory file. For instance, here is a common filter (see bf(-F)):
+
+quote(tt(--filter=': /.rsync-filter'))
+
+That rule tells rsync to scan for the file .rsync-filter in all
+directories from the root down through the parent directory of the
+transfer prior to the start of the normal directory scan of the file in
+the directories that are sent as a part of the transfer. (Note: for an
+rsync daemon, the root is always the same as the module's "path".)
+
+Some examples of this pre-scanning for per-directory files:
+
+quote(
+tt(rsync -avF /src/path/ /dest/dir)nl()
+tt(rsync -av --filter=': ../../.rsync-filter' /src/path/ /dest/dir)nl()
+tt(rsync -av --filter=': .rsync-filter' /src/path/ /dest/dir)nl()
+)
+
+The first two commands above will look for ".rsync-filter" in "/" and
+"/src" before the normal scan begins looking for the file in "/src/path"
+and its subdirectories. The last command avoids the parent-dir scan
+and only looks for the ".rsync-filter" files in each directory that is
+a part of the transfer.
+
+If you want to include the contents of a ".cvsignore" in your patterns,
+you should use the rule ":C", which creates a dir-merge of the .cvsignore
+file, but parsed in a CVS-compatible manner. You can
+use this to affect where the bf(--cvs-exclude) (bf(-C)) option's inclusion of the
+per-directory .cvsignore file gets placed into your rules by putting the
+":C" wherever you like in your filter rules. Without this, rsync would
+add the dir-merge rule for the .cvsignore file at the end of all your other
+rules (giving it a lower priority than your command-line rules). For
+example:
+
+quote(
+tt(cat <<EOT | rsync -avC --filter='. -' a/ b)nl()
+tt(+ foo.o)nl()
+tt(:C)nl()
+tt(- *.old)nl()
+tt(EOT)nl()
+tt(rsync -avC --include=foo.o -f :C --exclude='*.old' a/ b)nl()
+)
+
+Both of the above rsync commands are identical. Each one will merge all
+the per-directory .cvsignore rules in the middle of the list rather than
+at the end. This allows their dir-specific rules to supersede the rules
+that follow the :C instead of being subservient to all your rules. To
+affect the other CVS exclude rules (i.e. the default list of exclusions,
+the contents of $HOME/.cvsignore, and the value of $CVSIGNORE) you should
+omit the bf(-C) command-line option and instead insert a "-C" rule into
+your filter rules; e.g. "bf(--filter=-C)".
+
+manpagesection(LIST-CLEARING FILTER RULE)
+
+You can clear the current include/exclude list by using the "!" filter
+rule (as introduced in the FILTER RULES section above). The "current"
+list is either the global list of rules (if the rule is encountered while
+parsing the filter options) or a set of per-directory rules (which are
+inherited in their own sub-list, so a subdirectory can use this to clear
+out the parent's rules).
+
+manpagesection(ANCHORING INCLUDE/EXCLUDE PATTERNS)
+
+As mentioned earlier, global include/exclude patterns are anchored at the
+"root of the transfer" (as opposed to per-directory patterns, which are
+anchored at the merge-file's directory). If you think of the transfer as
+a subtree of names that are being sent from sender to receiver, the
+transfer-root is where the tree starts to be duplicated in the destination
+directory. This root governs where patterns that start with a / match.