You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在含GNU Parallel的Bash脚本中Zsh会展开Rsync通配符?

为什么Zsh会自动展开Rsync的--exclude通配符?

咱们来拆解下你遇到的问题:同样的脚本在Bash里正常跑,到Zsh就报错zsh:1: no matches found: *to?be?deleted*,核心原因是Bash和Zsh对通配符的默认处理逻辑不一样,再加上GNU Parallel的shell调用规则推波助澜。

问题根源

  1. Bash vs Zsh的通配符行为差异

    • Bash默认情况下,如果一个通配符模式(比如*to?be?deleted*)在当前目录找不到匹配的文件,它会直接把这个模式当作普通字符串传给后续命令(也就是让Rsync自己去解析这个通配符)。
    • Zsh的默认规则更严格:如果通配符没匹配到任何文件,它不会保留原字符串,而是直接抛出“找不到匹配项”的错误,根本不会把参数传给Rsync。
  2. GNU Parallel的“帮倒忙”
    如果你当前的登录shell是Zsh,GNU Parallel默认会用Zsh来执行你指定的Rsync命令。这就意味着,--exclude后面的通配符会先被Zsh解析一遍,而不是直接交给Rsync处理——这就是报错的直接触发点。

解决办法

给你几个靠谱的方案,按需选择:

1. 强制Parallel用Bash执行命令

这是最稳妥的方案,直接让Parallel用Bash来处理Rsync命令,和你原来的工作环境保持一致:

parallel --shell /bin/bash rsync --exclude '*to?be?deleted*' ... --files-from some_file /auto $instance_ip:/somewhere_else/

通过--shell /bin/bash参数,指定Parallel用Bash解析命令,这样通配符就会被原封不动传给Rsync了。

2. 给通配符加转义,阻止Zsh展开

如果你不想改Parallel的shell设置,可以把通配符里的特殊字符(*和?)用反斜杠转义,或者把整个模式用单引号嵌套包裹,确保Zsh不会提前解析:

# 方法1:逐个转义特殊字符
parallel rsync --exclude \*to\?be\?deleted\* ... --files-from some_file /auto $instance_ip:/somewhere_else/

# 方法2:嵌套单引号(适合Zsh环境下直接执行)
parallel rsync --exclude \'*to?be?deleted*\' ... --files-from some_file /auto $instance_ip:/somewhere_else/

3. 临时修改Zsh的通配符规则

如果你只是临时在Zsh环境下执行命令,可以暂时关闭Zsh的nonomatch选项(这个选项就是导致通配符不匹配时报错的原因):

# 先关闭nonomatch
unsetopt nomatch
# 执行你的命令
parallel rsync --exclude '*to?be?deleted*' ... --files-from some_file /auto $instance_ip:/somewhere_else/
# 执行完恢复默认设置
setopt nomatch

这个方法适合临时场景,避免影响Zsh的其他默认行为。

内容的提问来源于stack exchange,提问作者OneRaynyDay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:14:00