Rsync
匹配是从父目录到子目录,如果排除了某个目录,那被排除目录的子目录的任何规则不再生效。
例如: exclude=’/var’ include=’var/opt’
**表示匹配这个地址的每一层
例如 /var/opt/**可以被理解为 include=“/” include=“/var” include=“/var/opt”
例如
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
man page
包含/排除模式规则
您可以通过使用“+”、“-”等过滤规则指定模式来包含和排除文件(如上面的过滤规则部分所述)。每个包含/排除规则都指定了一个模式,该模式与将要传输的文件的名称相匹配。这些模式可以采用多种形式:
- 如果模式以 a 开头,
/则它被锚定到文件层次结构中的特定位置,否则它与路径名的末尾匹配。这类似于^正则表达式中的前导。因此/foo将匹配“传输根”(对于全局规则)或合并文件的目录(对于每个目录规则)中的“foo”名称。一个不合格foo将匹配树中任何位置的“foo”名称,因为该算法是从上到下递归应用的;它的行为就像每个路径组件在文件名结尾处轮流。即使未锚定的“sub/foo”也会在层次结构中的任何点匹配,其中在名为“sub”的目录中找到“foo”。有关如何指定在传输的根处匹配的模式的完整讨论,请参阅关于 ANCHORING INCLUDE/EXCLUDE PATTERNS 的部分。 - 如果模式以 a 结尾,
/那么它只会匹配一个目录,而不是常规文件、符号链接或设备。 - rsync 通过检查模式是否包含以下三个通配符之一来选择进行简单的字符串匹配和通配符匹配:’
*‘、’?‘ 和 ‘[‘ 。 - ‘
*‘ 匹配任何路径组件,但它在斜线处停止。 - 使用 ‘
**‘ 来匹配任何东西,包括斜线。 - ‘
?‘ 匹配除斜杠 (/)之外的任何字符。 - ‘
[‘ 引入了一个字符类,例如[a-z]or[[:alpha:]]。 - 在通配符模式中,反斜杠可用于转义通配符,但在不存在通配符时按字面匹配。这意味着与没有通配符的模式相比,当模式包含通配符时,反斜杠删除的级别更高。例如,如果您将通配符添加到“
foo\bar”(与反斜杠匹配),您将需要使用“foo\\bar*”来避免“\b”变成“b”。 - 如果模式包含
/(不包括尾随 /)或“**”,则它与完整路径名匹配,包括任何前导目录。如果模式不包含 a/或 “**“,则它仅与文件名的最后一部分匹配。(请记住,该算法是递归应用的,因此“完整文件名”实际上可以是从起始目录向下的路径的任何部分。) - 尾随的“
dir_name/***”将匹配目录(就像指定了“dir_name/”)和目录中的所有内容(就像dir_name/**已经指定了“ ”)。此行为是在 2.6.7 版中添加的。
请注意,当使用--recursive( -r) 选项(由 暗示 -a)时,从左到右访问每个路径的每个子目录组件,每个目录都有机会在其内容之前排除。通过这种方式,包含/排除模式以递归方式应用于文件系统树中每个节点的路径名(传输内部的节点)。当 rsync 找到要发送的文件时,排除模式会使目录遍历阶段短路。
例如,要包含“ /foo/bar/baz”,不得排除目录“ /foo”和“ /foo/bar”。排除这些父目录之一会阻止检查其内容,切断 rsync 到这些路径的递归并使“ /foo/bar/baz”的包含无效(因为 rsync 无法匹配它在目录层次结构的截止部分中从未见过的内容) .
使用尾随“ *”规则时,概念路径排除尤其重要。例如,这行不通:
1
2
3+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *
这将失败,因为父目录“some”被 ‘ *‘ 规则排除,所以 rsync 从不访问“some”或“some/path”目录中的任何文件。一种解决方案是通过使用单个规则:“ + */”(将其放在“ - *”规则之前的某个位置)要求包含层次结构中的所有目录,并且可能使用该--prune-empty-dirs选项。另一种解决方案是为所有需要访问的父目录添加特定的包含规则。例如,这组规则工作正常:
1
2
3
4
5+ /some/
+ /some/path/
+ /some/path/this-file-is-found
+ /file-also-included
- *
以下是排除/包含匹配的一些示例:
- “
- *.o“ 将排除所有匹配的名称*.o - “
- /foo“ 将排除 transfer-root 目录中名为 foo 的文件(或目录) - “
- foo/“ 将排除任何名为 foo 的目录 - “
- /foo/*/bar“ 将排除位于 transfer-root 目录中名为 foo 的目录下两级的名为 bar 的任何文件 - “
- /foo/**/bar“ 将排除在 transfer-root 目录中名为 foo 的目录下两级或更多级名为 bar 的任何文件 - “
+ */“、”+ *.c“ 和 “- *“ 的组合将包含所有目录和 C 源文件,但不包含其他内容(另请参见--prune-empty-dirs选项) - “
+ foo/“、”+ foo/bar.c“ 和 “- *“ 的组合将仅包含 foo 目录和 foo/bar.c(必须明确包含 foo 目录,否则它将被 “*“排除)
在 “ +“ 或 “ -“之后接受以下修饰符:
A
/指定包含/排除规则应与当前项的绝对路径名匹配。例如,“-/ /etc/passwd”会在传输从“/etc”目录发送文件时排除 passwd 文件,而“-/subdir/foo”在名为“subdir”的目录中时将始终排除“foo” , 即使“foo”是当前传输的根。A
!指定如果模式匹配失败,包含/排除应该生效。例如,“-! */”将排除所有非目录。A
C用于指示所有全局 CVS 排除规则都应作为排除插入来代替“-C”。不应遵循任何 arg。An
s用于指示规则适用于发送方。当规则影响发送方时,它会阻止文件传输。除非--delete-excluded指定,否则默认规则会影响双方,在这种情况下,默认规则仅成为发送方。另请参阅隐藏 (H) 和显示 (S) 规则,它们是指定发送方包含/排除的另一种方法。An
r用于指示规则适用于接收方。当规则影响接收方时,它可以防止文件被删除。有关s更多信息,请参阅修饰符。另请参阅保护 (P) 和风险 (R) 规则,这是指定接收方包含/排除的另一种方法。A
p表示规则易腐烂,这意味着它在被删除的目录中被忽略。例如,-C排除诸如“CVS”和“*.o”之类的选项的默认规则被标记为易腐烂,并且不会阻止在源上删除的目录在目标上被删除。An
x表示规则影响 xattr 复制/删除操作中的 xattr 名称(因此在匹配文件/目录名称时被忽略)。如果未指定 xattr 匹配规则,则使用默认的 xattr 过滤规则(请参阅--xattrs选项)。
博客1 地址
关于rsync的过滤规则:
译者注:这部分其实是man page中关于client的过滤规则的条目!不过,我把daemon中的过滤规则也集合到了里,两部分对比着进行理解。
关于pattern和rule,个人理解是:pattern是用来匹配文件或目录的正则,而rule则是前缀+pattern,也即整条规则。如:
1 | |
这是三条规则(rule),规则开头的”+”或”-“是前缀,foo/等前缀后面的东西即pattern(模式)。
下面是正文:
首先,来看rsyncd.conf官方文档在filter部分的描述(daemon上的过滤规则):
daemon拥有自己的过滤链,来决定哪些文件允许被client访问。这个过滤链不会被发送到client,并且独立于client中已经指定的过滤规则。
当client拉文件时,那些被daemon过滤链排除的文件会被视为不存在;而当client往server推送文件时,会跳过那些被daemon过滤链排除的文件,并且server会返回client一个错误消息;(当同步文件时)被daemon过滤链排除的文件永远不会从模块中删除。
daemon过滤链由”filter”、”include from”、”include”、”exclude from”、”exclude”参数组成,并以此为先后(生效)顺序。
(译者注:关于规则的生效顺序,应该是最先匹配。rsyncd.conf文档明确指出include规则可以覆盖掉exclude规则,照此理解,如果发生冲突,后面的规则应该不会覆盖掉前面的规则。下面filter rules部分也提到,最先匹配的模式会生效,但是在include/exclude pattern rules部分也提到一个特殊例子,在排除父目录,特别是使用号匹配来排除父目录时,有些地方需要特别留意。
条目中还有一句话:Anchored patterns are anchored at the root of the module.大意似乎是:锚点模式标记的是模块根目录。下面还会有提到Anchored pattern。)
要阻止对整个目录的访问,必须排除该目录下的所有文件,最简单的方法是使用三个星号,如,想要阻止访问/secret,过滤规则就应该这样写:/secret/**
再来看rsync的man page对过滤规则的描述(client中的过滤规则),这部分内容很多,由FILTER RULES条目开始,包括了条目:INCLUDE/EXCLUDE PATTERN RULES、MERGE-FILE FILTER RULES、MERGE-FILE FILTER RULES、ANCHORING INCLUDE/EXCLUDE PATTERNS等。
filter rules:
filter规则允许选择传输哪些文件(include),跳过哪些文件(exclude)。filter规则既可以直接指定include/exclude模式,也可以指定一个获取include/exclude模式的途径(如从一个文件中读取)。
当建立了要传输的文件/目录列表后,rsync会依次核查它们是否符合include/exclude模式,匹配到的第一个模式会生效:如果符合exclude模式,则跳过该文件,如果符合include模式,不跳过该,如果不符合任何模式,文件也不会被跳过。
rsync按照命令行中filter规则顺序建立一个有序列表。filter规则的语法如下:
rule [pattern_or_filename]
rule,modfiers [pattern_or_filename]
可以使用完整规则名称,也可以使用简写名称,可用的规则前缀如下:
exclude, - :排除模式
include, + :包含模式
merge, . :指定一个merge-file,供多个规则读取
dir-merge, : :指定一个per-directory merge-file
hide, H :指定一个模式,符合该模式的文件将被隐藏,以防止传输
show, S :不隐藏符合该模式的文件
protect, p :指定一个模式来防止文件被删除
risk, R :符合该模式的文件不会被保护
clear, ! :清除当前的include/exclude模式列表(该选项无参数)
注:关于merge-file和per-directory,见下文。
如果使用简写形式,前面语法中rule和modefiers之间的逗号是可选的,紧跟着的pattern或filename(如果存在)之后必须有一个空格或下划线。
如果规则是从文件中读取的,那么文件中的空白行将被忽略,以#开头的行被视为注释。
注意:–include/–exclude命令行中的选项,不能完全依照上面filter规则的解释。–include/–exclude命令只允许使用指明的include/exclude模式加”!”标识(即:模式+标识)来清除(译者注:排除或许更准确)(文件或目录)列表。如果模式不以”- “(两个字符:减号和空格)或”+ “(两个字符:加号和空格)开头,那么,对于包含选项而言,规则将被解释为字符串前添加了”+”前缀;对于排除选项而言,规则将被解释为字符串前添加了”-“前缀。与之相反,–filter选项必须在规则开头包含一个简写或完整的规则名称。
另外要注意的是,每个–filter选项,–include选项,和–exclude选项只接受一个rule/pattern,如果想添加多个rule/pattern,可以在命令行中的重复这些选项,或在–filter选项中使用merge-file语法,或使用–include-from/–exclude-from选项。
include/exclude pattern ruls:
注:rsync的man page说,–include和–exclude是–filter选项的简化版。
你可以使用”+”、”-“等filter过滤规则来指定模式,用以包含和排除文件。每个include/exclude规则指定一个模式来匹配传输文件。模式可以有以下几种形式:
1)如果”/”出现在模式的开头,那么它标记了层级中的一个特殊位置(译者注:指的应该是文件系统的位置或完整路径的层次结构中的某一层次),否则,它只是匹配路径的结束。(译者注:这里又出现了anchor,计算机术语称之为锚点,它设置一个标记,然后可以在本文档或页面的其它地方创建一个指向本标记的链接:锚点,标记了一个特定位置。)因此,”/foo”将匹配”root of the transfer”中的foo(对全局规则而言),或者merge-file目录中的foo(对per-directory规则而言)。而未经限定的foo将匹配文件系统中任何位置的foo,因为算法是自上而下递归地生效,就像是路径的每个部分轮流变成文件或目录的结尾(译者注:例如foo/a/b/c,算法对该路径的解释将会是foo/a,foo/a/b,foo/a/b/c,算法依次把a、b、c作为文件或目录结尾)。实际上,非锚定的”sub/foo”将会匹配层次结构中包含子目录sub的,任何位置的foo。
2)如果”/”出现在模式的结尾,那么它只匹配目录,而不匹配常规文件、链接,或设备。
3)rsync会检查模式中是否包含下列通配符,以确定做简单的字符匹配还是通配符匹配:”*”、”?”、”[“
* :匹配路径的任何部分,遇到斜杠终止
** :匹配任何东西,包括斜杠
? :匹配任何单个字符,斜杠(“/”)除外
[ :匹配一个字符集,如[a-z],或[[:alpha:]]
4)在通配符模式中,反斜杠(“\”)对通配符进行转义,如果通配符不存在,它会被解释一个普通字符
5)如果模式包含”/”(尾部的”/”不计算在内)或””,它将匹配完整路径,包括前导目录(即foo/a,既匹配a,也匹配前导的foo);如果模式不包含”/”或””,它只匹配路径最后的部分。(注意:算法是递归地应用,所以实际上“完整路径”可能是从起始目录向下,路径的任何一个部分。)
6)以dir_name/***结尾的模式,既匹配目录(就像指定了dir_name/),又匹配目录中的所有文件(就像指定了dir_name/*)。
请注意:如果使用了-r选项(-a选项隐含了此选项),那么,自顶向下,路径的每一个部分都将被访问,所以,include/exclude模式会递归地对路径的每个组成部分生效(如,要包含/foo/bar/baz,就不能排除/foo和/foo/bar)。当rsync寻找要发送的文件时,exclude模式实际上是rsync在历遍目录时的一个短路。如果一个模式排除了特定的父目录,它就能使一个更深的include模式无法生效,因为rsync无法穿过层级中的排除部分而向下(匹配文件)。(译者注:意思应该是,如果模式排除一个指定的父目录,那么它将无法继续匹配该父目录下的子目录或文件。)这一点非常重要,尤其是使用一个以””结尾的规则时。如下:
+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *
上述规则链将无法得到你想要的结果,因为父目录some被”*”规则排除了,所以rsync不会去访问some或some/path目录下的任何文件。要解决这个问题,可以使用一个”+ */”规则来包含层级的所有目录(把它放到”- ”前面的任意位置),或许还需要–prune-empty-dirs选项。另外一个解决途径是,添加一个include规则来包含所有需要被访问的父目录。下例的规则集就可以很好的工作:
+ /some/
+ /some/path/
+ /some/path/this-file-is-found
+ /file-also-included
- *
(译者注:
1)不知道大家是否理解了上面的官方示例。第一个例子本想包含两个文件,但结果只包含到了一个。文件this-file-will-not-be-found没有被包含的原因在于:基于最先匹配原则,文件本身被include规则所匹配,但其父目录以及爷爷目录并没有被include规则所匹配,所以它们被后面的exclude规则所匹配,而由于rsync不能穿过被exclude规则排除的父目录而匹配其中的文件,所以该文件最终将无法出现在匹配结果中。
这一过程有三个关键:一是rsync无法穿过被排除的父目录而向下匹配文件;二是匹配路径任一部分,遇/终止匹配;三是最先匹配。
2)关于–prune-empty-dirs(简写模式为-m):这个命令行中的选项告诉rsync的接收方从文件列表中删除空目录,包括那些没有非空子目录的嵌套目录。这个选项很有用,当rsync的发送方使用include/exclude/filter规则扫描具有多层次结构的文件时,它可以避免(接收方)创建一系列无用的目录。)
下面是一些exclude/include匹配的示例:
- .o:排除所有以o结尾的文件
- /foo:排除transfer-root目录中,名为foo的文件或目录
(译者注:前面也提到了transfer-root,这个概念会在ANCHORING INCLUDE/EXCLUDE PATTERNS条目中讲到,举例来说明,有一个路径/home/me/foo/bar:
rsync -a - /me/foo/bar /home/me /dest
rsync -a - /foo/bar /home/me/ /dest
上述规则要复制/home/me目录及其下所有文件到/dest,但要排除/me/foo/bar文件(或目录)。两条规则的效果是一样的,但是transfer-root不同。第一条规则中,/home目录就是transfer-root;而对于第二条规则,/home/me/才是transfer-root。也就是说,transfer-root是从路径的最末位向前追溯,遇到的第一个以”/“结尾的目录。)
- foo/:排除任何名为foo的目录
- /foo//bar:从transfer-root中的foo目录向下两级的位置,排除名为bar的文件。
- /foo/**/bar:从transfer-root中的foo目录向下至少两级的位置,排除名为bar的文件。
+ */c,+ *.c,和- *的组合,会包含所有目录,以及以c结尾的文件,除此之外,所有文件都排除。
+ /foo/,+ foo/bar.c,和- 的组合,将只包含foo目录,以及foo/bar.c文件。(必须明确包含foo目录,否则它将被exclude规则中的所匹配,这会导致前面所讲到的排除特定父目录的问题,将无法如你所愿匹配到foo/bar.c文件。)
“+”或”-“接受下列修饰符:
/,指定include/exclude规则要匹配当前项目的绝对路径。例如,-/ /etc/passwd,每当从/etc目录中传输文件时,都要排除密码文件;再比如,-/ subdir/foo,当从名为subdir的目录中传输文件时,总是排除文件foo,即使该文件位于当前传输的根目录。
译者注:不要混淆匹配模式中的/和修饰符/ !
!,告诉rsync,当模式匹配失败时,include/exclude规则才生效。如,-! */,它将匹配所有非目录文件。
C,该修饰符指示,所有全局的CVS-exclude规则将插入到-C的地方。该修饰符后面无参数。(译者注:文档在介绍-C –cvs-exclude选项时说,如果在自己的–filter规则中同时使用-C,那么所有的CVS exclude规则将附加到你自己的规则的末尾,不管-C位于命令行的什么地方。)
s,指示规则作用于发送端。当规则对发送端生效时,它将阻止文件被传输。该修饰符通常用于那些在两端都生效的规则,除非指定了–delete-excluded;它将使规则默认只在发送端生效。另一种指定发送端includes/excludes的途经是使用hide(H)和show(S)。
r,通常用来指示规则应用于接收端。当规则对接收方生效时,它将防止文件被删除。另一种指定接收端includes/excludes的方法是,使用protect(P)和risk(R)规则。
本文转自 li_qinshan 51CTO博客,原文链接:http://blog.51cto.com/share/567578
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
博客2 地址
rsync –include-from –exclude-from的理解:
1、同时添加–include-from –exclude-from时。后者是对前者的结果进行排除
如:“–include-from include.txt –include-from exclude.txt” #也就是说绝对不会超过–include-from声明的范围
2、–include-from 文件前面的符号是有效的有意义的
3、–exclude-from 文件前面不管是什么符号、有没有符号都是排除的意思
4、每一个目录、子目录、文件都会与这个过滤规则列表进行匹配,直到找到一个命中的(命中的规则说要过滤就过滤,要包含那就包含),
5、最重要的一个原则: 只找第一个匹配的规则
以下是原文,我把关键词标出来方便阅读:
FILTER RULES
The filter rules allow for flexible selection of which files to transfer (include) and which files to skip (exclude). The rules either directly specify include/exclude patterns or they specify a way to acquire more include/exclude patterns (e.g. to read them from a file).
As the list of files/directories to transfer is built, rsync checks each name to be transferred against the list of include/exclude patterns in turn, and the first matching pattern is acted on: if it is an exclude pattern, then that file is skipped; if it is an include pattern then that filename is not skipped; if no matching pattern is found, then the filename is not skipped.
Rsync builds an ordered list of filter rules as specified on the command-line.
以下是一个实例后面添加对相关过滤规则的说明和理解
#############################################################################
### include.txt:
# CompanyAttachment Files
# 限制所有目录只包含2019开头的
- ETest/20191/ #如果非要排除 ETest/20191下的文件 这个排除规则应该放前面。每个路径 只找第一个匹配的规则 ( 只找第一个、只找第一个、只找第一个 这很重要,理解了这个原则,才能理解所有的规则)
+ 2019*/ #这个只是 包含了目录,目录下的文件不会同步
+ 2019*/** #这个只包含了目录下的文件,如果没有上面的这个也无效
+ ETest/ #这个只是 包含了目录 但是子目录如果符合上面的其它条件也会被同步(如ETest目录下有2019开头的文件夹,也会同步)
- * #排除其它文件
- *.tmp #排除所有的.tmp文件。 这是个 错误 的示例,这个不一定会排除所有目录的.tmp文件。因为有些路径会命中前面的规则就直接返回了。这个排除规则要么写到最前面,要么写到exclude.txt里去
#############################################################################
#############################################################################
# exclude.txt
*.tmp #exclude-from文件里不管前面加不加+、-号都是排除(测试+号、-号、不要符号结果是一样的,很奇怪,但测试结果是这样,不知道我是不是理解错误)
#* #exclude-from 是对include-from的结果进行排除,所以不能加这个。这个相当于禁用同步了。
#############################################################################
总结一下:
1、顺序很重要,重要的、命中范围小的写前面
2、最重要的还是理解它的过滤逻辑:每一个目录、子目录、文件都会与这个过滤规则列表进行匹配,直到找到一个命中的(命中的规则说要过滤就过滤,要包含那就包含),
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!