我正在尝试创建一个目录来存放所有且仅由 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/foo
a/foo
rsync -r a b
b/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 尝试将模式扩展为相对于当前目录的文件名,并执行以下操作之一:
成功并弄乱你的过滤器(不太可能在这样的标志中间,尽管你真的不知道什么时候有人会创建一个名为
--include=foo.pdf
...的文件)失败,并且可能会产生错误而不是运行命令(正如您发现 zsh 默认情况下所做的那样)。