rsync 使用 include-from 仅同步特定文件或目录

aar*_*rkk 1 linux rsync command-line

这似乎是一个非常简单的请求,但我已经用 rsync 将头撞在墙上大约一个小时了,所以我想我只是问一下。我只是尝试使用 rsync 将本地目录到远程目录中的一组特定文件列入白名单。

让我们想象一下,现在我只想发送*.ts根目录中的文件。因此,将其想象为源结构:

/foo
  bar.ts
  baz.ts
  package.json
  node_modules/...
  other_dir/...
Run Code Online (Sandbox Code Playgroud)

在此示例中,我只想发送bar.tsbaz.ts

想做的就是这样:

rsync --include-from include.txt foo remotehost:foo

其中include.txt仅包含:

*.ts
Run Code Online (Sandbox Code Playgroud)

当我尝试这样做时,我发现skipping directory .如果我有一个列表,为什么会发生这种情况include-from

所以然后我尝试使用存档/递归模式(但这不是我想要的,因为我只是想指定一个列表......但无论如何让我们尝试一下):

rsync -a --include-from include.txt foo remotehost:foo

这样就复制了所有内容foo并忽略了include-from.

然后我尝试了:

rsync -a --exclude '*' --include-from include.txt foo remotehost:foo

我认为模式是从左到右评估的,所以我希望这仅包括我的列表中的文件,但它排除了它们,因为它们与模式“*”匹配

再说一遍,这似乎是一件非常基本的事情,我不知道为什么让 rsync 做到这一点如此具有挑战性。

我在这里缺少什么?

Gor*_*son 6

让我从最简单的解决方案开始,然后回顾一下为什么您的尝试没有达到您的预期。尝试这个:

rsync foo/*.ts remotehost:foo
Run Code Online (Sandbox Code Playgroud)

请注意,shell 在运行之前扩展了通配符rsync,因此这基本上相当于:

rsync foo/bar.ts foo/baz.ts remotehost:foo
Run Code Online (Sandbox Code Playgroud)

编辑:经过评论中的讨论,我认为根本问题是规则名称“ include”有点误导;称它们为“不排除”规则可能会更清楚,甚至更好的是“即使过滤器列表后面有一个排除规则,也不要排除”(但这些规则很详细,而不是 shell 脚本语法)友好,所以“排除”它)。

这样说:-r-a告诉rsync在源目录内传输文件/子文件夹,“排除”规则允许您对此进行例外处理(即跳过一些将被传输的项目),而“包含”规则则允许您进行例外处理例外中的例外(即转移稍后“排除”规则将排除的项目)。

现在,让我们回顾一下不起作用的命令:

rsync --include-from include.txt foo remotehost:foo
Run Code Online (Sandbox Code Playgroud)

这里的问题是您告诉它同步目录(foo),而不是该目录中的文件。使用-r(或-a) 选项,它不会执行此操作,因此它只是跳过该目录。所以,你添加-a

rsync -a --include-from include.txt foo remotehost:foo
Run Code Online (Sandbox Code Playgroud)

...现在它发送所有内容,因为您给了它一个要包含的内容列表,但没有告诉它排除任何内容。默认情况下是包含某些内容,并且添加显式指令以包含特定内容不会改变这一点。

所以你添加一条排除指令:

rsync -a --exclude '*' --include-from include.txt foo remotehost:foo
Run Code Online (Sandbox Code Playgroud)

...但是您将排除规则放在第一位,它会从左到右检查规则,对第一个匹配项进行操作。由于所有内容都匹配*,因此所有内容都被排除,并且文件中的包含规则永远不会被应用。

您应该能够通过将包含规则放在第一位来使其工作:

rsync -a --include-from include.txt --exclude '*' foo remotehost:foo
Run Code Online (Sandbox Code Playgroud)

...但正如我在一开始所建议的那样,让 shell 通配符进行匹配会更容易。尽管如果您将文件从远程复制到本地,则需要使用类似的方法,因为您的本地 shell 无法应用远程通配符。