rsync: --include-from 和 --exclude-from 有什么实际区别?

34
在文档中,提到这些文件包含要包含或要排除的模式列表。然而,这意味着对于包含文件,除了匹配模式的内容,其他所有内容都被视为排除。例如,一个包含以下内容的包含文件:
/opt/**.cfg

只应包括任何以*.cfg命名的文件,这些文件存在于名为opt的目录下的任何位置。因此,它将匹配以下内容:

/opt/etc/myfile.cfg
/some/dir/opt/myfile.cfg
/notopt/opt/some/other/dir/myfile.cfg

因此,我期望它会隐式地排除任何其他内容。但是,看起来并非如此,因为我在项目化输出中看到了这个东西:
*deleting   etc/rc.d/init.d/somescript
< p >那么,--include-from--exclude-from是什么意思呢?它们只是--filter-from的别名吗?< /p >
2个回答

99

rsync 不是那样工作的。任何文件名模式不匹配任何包含或排除模式的文件都被认为是包含在内的。换句话说,可以将包含模式视为覆盖排除模式的一种方式。

来自文档(重点在于我):

rsync按照命令行上指定的包含/排除选项构建一个有序列表。rsync依次检查每个文件和目录名称与每个排除/包含模式是否匹配。首先匹配的模式将被执行。如果它是一个排除模式,则跳过该文件。如果它是包含模式,则不跳过该文件名。如果未找到匹配的包含/排除模式,则不跳过该文件名。

因此,如果您只想包含特定文件,则首先需要包含这些特定文件,然后排除所有其他文件:

--include="*/" --include="*.cfg" --exclude="*"

有几件事情需要注意:

  1. 要放在排除规则之前的是“包含”模式,因为第一个匹配的模式会被考虑。如果文件名首先匹配了排除模式,那么它会被排除。

  2. 您需要单独包括所有子目录,比如--include="/opt" --include="/opt/dir1"等,或者使用--include="*/"来包括所有目录(而不是文件)。出于简洁起见,我选择了第二个选项。

这很古怪,不太直观。因此,请仔细阅读文档(链接中的“排除模式”部分),并使用--dry-run-n选项确保它将执行您认为应该执行的操作。


这很有道理。我实际上是用它来验证在排除和包含列表范围之外是否存在模糊的文件。我首先运行时将所有内容都排除,只同步明确包含的内容。然后我再次运行相同的命令,这次包括所有内容,只有明确排除的内容不会被同步。然后对项目化日志进行差异比较,并显示任何未被任何模式匹配的模糊文件。这确保了没有意外修改。 - Craig
4
实际上,即使是我的示例也不起作用。 因为 exclude=* 排除了一切,而这是第一个匹配的模式,所以没有任何东西被传输。 我已将其更改为首先具有包含模式。 - Hari Menon
最后,--filter="merge exclude_list"--filter="merge include_list"就足够了。我在每个规则底部创建了一个隐式规则来排除/包含任何未匹配到的内容。现在它的行为符合预期。谢谢! - Craig
5
这是我迄今为止看过的最好的解释奇怪的rsync规则。 - Max
2
不要忘记使用“-m”选项,以避免创建大量空目录树。 - John Tyree
显示剩余2条评论

6
如果你(像我一样)很难理解man手册中的“FILTER RULES”部分,但是对find有基本的了解,那么可以使用find代替。假设你想要将文件名或目录名中带有特定日期(例如“2016-02-01”)的文件从/storage/data同步到rsync_test文件夹,可以执行以下命令:
cd /storage/data
find . -name '*2016-02-01*' \
  | rsync --dry-run -arv --files-from=- /storage/data /tmp/rsync_test

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接