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

Sea*_*mus 178 backup rsync wildcards

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

rsync -avn *.pdf ~/LaTeX/ ~/Output/
Run Code Online (Sandbox Code Playgroud)

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

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

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


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

rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/
Run Code Online (Sandbox Code Playgroud)

这给了我整个文件列表。我猜是因为一切都匹配第一个模式......

Gil*_*il' 334

TL,博士:

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/
Run Code Online (Sandbox Code Playgroud)

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

所以你需要运行rsync -a ~/LaTeX/ ~/Output/, 但使用过滤器告诉 rsync.pdf只复制文件。当您阅读手册时,Rsync 的过滤规则似乎令人生畏,但是您可以使用一些简单的规则构建许多示例。

  • 包含和排除:

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

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


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

rsync -a --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/
Run Code Online (Sandbox Code Playgroud)

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

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/
Run Code Online (Sandbox Code Playgroud)


jma*_*g2k 40

rsync -av --include="*/" --include="*.pdf" --exclude="*" ~/Latex/ ~/Output/ --dry-run
Run Code Online (Sandbox Code Playgroud)

默认是包含所有内容,因此您必须包含要传输的文件明确排除所有内容。删除 --dry-run 以实际传输文件。

如果你开始:

--exclude '*' --include '*.pdf'
Run Code Online (Sandbox Code Playgroud)

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

如果你试试:

--include '*.pdf' --exclude '*' 
Run Code Online (Sandbox Code Playgroud)

然后只会传输顶级文件夹中的 pdf 文件。它不会跟随任何目录,因为那些被“*”排除在外。

  • 截至 2014 年 3 月 17 日,这是最佳答案,因为它解决了原始海报问题**完全**。请投票!如果您添加`--prune-empty-dirs`(或快捷方式`-m`),您甚至可以在目的地为自己节省许多空目录,当然您希望它们作为提醒或结构蓝图。 (6认同)
  • 最佳答案, --include="*/" 是关键。 (3认同)

Mar*_*erg 15

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

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

rsync -avn ~/LaTeX/**/*.pdf ~/Output/
Run Code Online (Sandbox Code Playgroud)


小智 14

您可以使用find和 中间文件列表 ( files_to_copy) 来解决您的问题。确保您位于主目录中,然后:

find LaTeX/ -type f -a -iname "*.pdf" > files_to_copy && rsync -avn --files-from=files_to_copy ~/ ~/Output/ && rm files_to_copy

用 Bash 测试。

  • rsync 选项`--files-from` 接受从标准输入读取。这将工作`find LaTeX/ -type f -a -iname "*.pdf" | rsync -avn --files-from=- ~/ ~/Output/` (2认同)

Sam*_*amB 9

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

rsync -avn --include="*/" --include="*.pdf" ~/Latex/ ~/Output/
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 你需要在 `--include="*.pdf"` 之后的 `--exclude="*"`,否则这会传输所有内容。 (7认同)

gue*_*tli 5

这是我的首选解决方案:

find source_dir -iname '*.jpg' -print0 |  rsync -0 -v --files-from=- . destination_dir/
Run Code Online (Sandbox Code Playgroud)

find命令比rsync:-)的包含/排除规则更容易理解

如果您只想复制pdf文件,只需更改.jpg.pdf