排除由 rsync 复制的具有特定扩展名集的文件

Excluding files with a certain set of extensions to be copied by rsync

问题:从 Zsh 脚本调用 rsync,我想告诉 rsync 排除具有一组特定扩展名之一的文件。我现在这样做的方式是:

rsync -r --exclude '*.bak' --exclude '*.save' --exclude '*.backup' --exclude '*.old' ... from_directory/* to_directory

写起来很乏味,命令行也很长。我试过替代方案

# THIS DOES NOT WORK:
rsync -r --exclude '*.bak' --exclude '*.{save,backup,old,...}' from_directory/* to_directory

但这不起作用 - rsync 不处理使用大括号的快捷方式(这并不奇怪,因为即使在 shell 级别,这也不是文件通配,但发生在命令行解释的早期阶段)。

我也考虑过将所有要排除的模式写入文件并使用--exclude-list而不是--exclude。这可行,但我不喜欢这个解决方案,因为我希望我的脚本是独立的,即文件模式在脚本中可见,而不是在单独的文件中。

当然,总有一个解决方案可以使用 HERE 文档创建包含扩展名的临时文件:

cat <<<LIST >excluded.txt
*.bak
*.save
... etc
LIST
rsync -r --exclude-list excluded.txt ....
rm excluded.txt

但我想知道是否有更优雅的解决方案,或者通过一些巧妙地使用 rsync 选项,或者通过一些 Zsh 功能使处理临时文件更容易。

您尝试的替代方案不起作用,因为大括号扩展 (foo{a,b,c}barfooabar foobbar foocbar) 没有为带引号的大括号完成。

试试下面的方法。

rsync -r --exclude='*'.{bak,save,backup,old} from_directory/* to_directory

诀窍是只引用 * 并利用 --exclude 选项的值也可以用 = 分隔而不是 space 的事实.这样 zsh 将其识别为一个词并且

--exclude='*'.{bak,save,backup,old}

将扩展到

--exclude='*'.bak --exclude='*'.save --exclude='*'.backup --exclude='*'.old