Rsync 过滤器:仅复制一种模式

Rsync 过滤器:仅复制一种模式

我正在尝试创建一个目录来存放所有且仅由 LaTeX 编译的 PDF。我喜欢将每个项目保存在一个单独的文件夹中,所有项目都放在一个名为LaTeX.所以我尝试运行:

rsync -avn *.pdf ~/LaTeX/ ~/Output/

它应该找到所有 pdf 文件~/LaTeX/并将它们传输到输出文件夹。这是行不通的。它告诉我没有找到“ *.pdf”的匹配项。如果我省略此过滤器,该命令会列出 LaTeX 下所有项目文件夹中的所有文件。所以这是 *.pdf 过滤器的问题。我尝试替换~/为我的主目录的完整路径,但这没有效果。

我正在使用 zsh。我尝试在 bash 中做同样的事情,甚至列出每个子目录中每个文件的过滤器...这是怎么回事?

为什么 rsync 不理解我的仅 pdf 过滤器?


好的。所以更新:不,我正在尝试

rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/

这给了我整个文件列表。我想是因为一切都符合第一个模式......

答案1

TL、博士:

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Rsync 将源复制到目标。如果作为源传递,shell 会将其扩展为当前目录中*.pdf具有扩展名的文件列表。.pdf不会发生递归遍历,因为您没有传递任何目录作为源。

因此,您需要运行,但使用过滤器来告诉 rsync仅rsync -a ~/LaTeX/ ~/Output/复制文件。.pdf当您阅读手册时,Rsync 的过滤规则可能会让人望而生畏,但是您可以仅用一些简单的规则构建许多示例。

  • 包含和排除:

    • 按名称或按位置排除文件很容易:--exclude=*~, --exclude=/some/relative/location(相对于源参数,例如排除~/LaTeX/some/relative/location)。
    • 如果您只想匹配几个文件或位置,请包含它们,包括指向它们的每个目录(例如使用--include=*/),然后使用 排除其余部分--exclude='*'。这是因为:
    • 如果排除某个目录,则会排除该目录下的所有内容。根本不会考虑排除的文件。
    • 如果包含目录,则不会自动包含其内容。在最近的版本中,--include='directory/***'将这样做。
    • 对于每个文件,应用第一个匹配规则(并且包括任何从未匹配的内容)。
  • 图案:

    • 如果模式不包含/,则它适用于无目录的文件名。
    • 如果模式以 结尾/,则它仅适用于目录。
    • 如果模式以 开头/,则它适用于作为参数传递给 的目录中的整个路径rsync
    • *单个目录组件的任何子字符串(即从不匹配/);**匹配任何路径子字符串。
  • 如果源参数以 a 结尾/,则复制其内容(为 everyrsync -r a/ b创建)。否则目录本身将被复制(创建)。b/fooa/foorsync -r a bb/a


因此,这里我们需要 include *.pdf,包括包含它们的目录,并排除其他所有内容。

rsync -a --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

请注意,这会复制所有目录,甚至是不包含匹配文件的目录或包含匹配文件的子目录。可以使用该--prune-empty-dirs选项来避免这种情况(这不是通用解决方案,因为即使通过显式匹配也无法复制目录,但这是一个罕见的要求)。

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

答案2

rsync -av --include="*/" --include="*.pdf" --exclude="*" ~/Latex/ ~/Output/ --dry-run

默认情况下包含所有内容,因此您必须显式排除所有内容包括您要传输的文件。删除 --dry-run 以实际传输文件。

如果你从以下开始:

--exclude '*' --include '*.pdf'

然后贪婪匹配将立即排除所有内容。

如果你试试:

--include '*.pdf' --exclude '*' 

那么只有顶层文件夹中的 pdf 文件才会被传输。它不会跟随任何目录,因为这些目录被“*”排除。

答案3

如果您使用类似 的模式*.pdf,shell 会“扩展”该模式,即用当前目录中的所有匹配项替换该模式。您正在运行的命令(在本例中为 rsync)不知道您尝试使用模式的事实。

当您使用时桀骜不过,有一个简单的解决方案:该**模式可用于递归地匹配文件夹。尝试这个:

rsync -avn ~/LaTeX/**/*.pdf ~/Output/

答案4

从“包含/排除模式规则”部分来看联机帮助页,这样做的方法是

rsync -avn --include="*/" --include="*.pdf" ~/Latex/ ~/Output/

这个和 kbrd 的答案之间的关键区别是--include="*/"标志,它告诉 rsync 继续复制它找到的任何目录,无论它们的名称是什么。这是必需的,因为 rsync 不会递归到子目录,除非已指示它复制该子目录。

另请注意,引号会阻止 shell 尝试将模式扩展为相对于当前目录的文件名,并执行以下操作之一:

  1. 成功并弄乱你的过滤器(不太可能在这样的标志中间,尽管你真的不知道什么时候有人会创建一个名为--include=foo.pdf...的文件)

  2. 失败,并且可能会产生错误而不是运行命令(正如您发现 zsh 默认情况下所做的那样)。

相关内容