如何使用 rsync 包含和排除来捕获分布式文件集?

eri*_*son 2 backup rsync file-transfer

我正在尝试使用 rsync 备份机器,在阅读了大量 SO QA 和手册页后,我仍然无法理解包含/排除优先级如何工作,以便我可以传输正确的文件集。混淆具体细节,我正在尝试以下操作:

递归包含:

/home/erik/foo
/home/erik/bar
/home/erik/baz
Run Code Online (Sandbox Code Playgroud)

递归地包含 /git,但排除一些特定的子目录,例如 /git/src/github.com/foo 和 /git/src/github.com/bar。

到目前为止,我认为 rsync 命令应该可以完成此任务。事实并非如此,我尝试了许多以不同方式失败的变体:

rsync -am \
  --include='*/' \
  --include='/home/erik/foo' \
  --include='/home/erik/bar' \
  --include='/home/erik/baz' \
  --include='/git' \
  --exclude='/git/bin' \
  --exclude='/git/src/github.com/foo' \
  --exclude='/git/src/github.com/bar' \
  --exclude='*' \
  / nfs.example.com:/data/pool/backup/laptop
Run Code Online (Sandbox Code Playgroud)

一些具体问题:

  • 我已经多次看到它建议最初的 --include='*/ 是必要的,尽管我不完全确定为什么。我认为它与确保目录扩展和遵循有关(?)。我还假设最终排除是排除与更高语句不匹配的任何文件?有人可以详细说明这些是否都是必要的,并且它们的立场是否重要?

  • 我不确定目录是否需要前导 /。我已经看到这些路径与请求的 / 传输根相关的提示,这表明它应该类似于 home/erik,但我也没有成功。有人可以扩展一下这是如何工作的吗?

  • 我不确定如果我想包含目录和所有子内容,路径中是否需要后缀 / ?

  • 有人可以详细说明参数的位置是否实际上很重要,即将应用列表中第一个匹配的位置?

  • 有什么理由让我更喜欢 --filter='+ X' 而不是 --include ?排除也一样吗?

roa*_*ima 5

您的命令非常接近工作解决方案。让我们把它分解一下,因为我认为这也能回答你的具体问题。

\n
    \n
  • rsync -am- 还复制明显的文件元数据属性(权限、所有权、时间);不要在目标上创建空目录
  • \n
  • --include='*/'- 包括所有目录(尾随/仅匹配目录)
  • \n
  • --include='/home/erik/foo'- 包含此路径(foo可能是文件或目录;我们无法判断)
  • \n
  • --include='/home/erik/bar'- 同样对于bar
  • \n
  • --include='/home/erik/baz'- 和baz
  • \n
  • --include='/git'- 包括最顶层git(前导/绑定到源树的顶部;我们无法从参数中判断是否git文件还是目录)
  • \n
  • --exclude='/git/bin'bin- 排除位于最顶层的文件或目录(如果它是一个目录,则也隐含其下的所有内容)git目录
  • \n
  • --exclude='/git/src/github.com/foo'-foo排除/git/bin上述
  • \n
  • --exclude='/git/src/github.com/bar'- 和bar还有
  • \n
  • --exclude='*'- 排除我们尚未明确包含的所有文件或目录
  • \n
  • / nfs.example.com:/data/pool/backup/laptop- 复制自/到 NFS 服务器上的路径
  • \n
\n

首先要记住的是,操作是从左到右(从第一个到最后一个)处理的,并且第一个匹配获胜。这意味着您的所有include语句都将覆盖exclude语句。

\n

我会添加-v标志 ( --verbose),以便我可以看到一些正在发生的情况,以及-n用于测试的标志 ( --dry-run)。erik您立即可以看到除了可能的s之外,您还没有包含任何文件foobar并且baz

\n
rsync --dry-run --verbose --archive --prune-empty-dirs \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

**通配符***在这里会很有用(**包括当前点下的所有文件和目录;***也适用于当前点本身):

\n
--include='/home/erik/foo/***'\n--include='/home/erik/bar/***'\n--include='/home/erik/baz/***'\n
Run Code Online (Sandbox Code Playgroud)\n

排除git树的某些部分以及下面的所有关联文件/目录

\n
--exclude='/git/bin/***'\n--exclude='/git/src/github.com/foo/***'\n--exclude='/git/src/github.com/bar/***'\n
Run Code Online (Sandbox Code Playgroud)\n

现在包括(剩下的)git

\n
--include='/git/***'\n
Run Code Online (Sandbox Code Playgroud)\n

差不多了。要查找顶层以外的目录和文件,我们必须搜索所有目录,因此让我们包含这些目录,然后使用-prune-empty-dirs丢弃空目录

\n
--include='*/'\n
Run Code Online (Sandbox Code Playgroud)\n

最后,我们可以排除其他一切

\n
--exclude='*'\n
Run Code Online (Sandbox Code Playgroud)\n

因此最终的命令是

\n
rsync --dry-run --verbose --archive --prune-empty-dirs \\\n  --include='/home/erik/foo/***' \\\n  --include='/home/erik/bar/***' \\\n  --include='/home/erik/baz/***' \\\n  --exclude='/git/bin/***' \\\n  --exclude='/git/src/github.com/foo/***' \\\n  --exclude='/git/src/github.com/bar/***' \\\n  --include='/git/***' \\\n  --include='*/' \\\n  --exclude='*' \\\n  / nfs.example.com:/data/pool/backup/laptop\n
Run Code Online (Sandbox Code Playgroud)\n