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:
merge /etc/rsync/default.rules
. /etc/rsync/default.rules
dir-merge .per-dir-filter
dir-merge,n- .non-inherited-per-dir-excludes
:n- .non-inherited-per-dir-excludes
The following modifiers are accepted after a merge or dir-merge
rule:
o A -
specifies that the file should consist of only exclude
patterns, with no other rule-parsing except for in-file
comments.
o A +
specifies that the file should consist of only include
patterns, with no other rule-parsing except for in-file
comments.
o A 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.
o A e
will exclude the merge-file name from the transfer;
e.g. "dir-merge,e .rules" is like "dir-merge .rules" and
"- .rules".
o An n
specifies that the rules are not inherited by
subdirectories.
o A 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).
o You may also specify any of the modifiers for the "+" or
"-" rules (above) in order to have the rules that are read
in from the file default to having that modifier set
(except for the !
modifier, which would not be useful).
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. If the merge rule
specifies sides to affect (via the s
or r
modifier or
both), then the rules in the file must not specify sides
(via a modifier or a rule prefix such as hide
).
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
--filter=". file":
merge /home/user/.global-filter
- *.gz
dir-merge .rules
+ *.[ch]
- *.o
- foo*
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 -F
):
--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:
rsync -avF /src/path/ /dest/dir
rsync -av --filter=': ../../.rsync-filter' /src/path/ /dest/dir
rsync -av --filter=': .rsync-filter' /src/path/ /dest/dir
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 --cvs-exclude
(-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:
cat <<EOT | rsync -avC --filter='. -' a/ b
+ foo.o
:C
- *.old
EOT
rsync -avC --include=foo.o -f :C --exclude='*.old' a/ b
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 -C
command-line option and instead insert a "-C" rule into
your filter rules; e.g. "--filter=-C
".