下面的脚本在 bash 中有效,但在 zsh 中无效。我认为这是因为在变量中OPTS,我正在“扩展”(不确定这是否是正确的词)变量$EXCLUDE,而这种语法在 zsh 中不起作用。我将如何替换该行以使其在 zsh 上工作?
SRC="/path_to_source"
DST="/path_to_dest"
EXCLUDE=".hg"
OPTS="-avr --delete --progress --exclude=${EXCLUDE} --delete-excluded"
rsync $OPTS $SRC $DST
Run Code Online (Sandbox Code Playgroud)
Sté*_*nez 22
这里的问题$OPTS是没有在rsync命令行上分成几个参数。在zsh语法中,使用:
rsync ${=OPTS} $SRC $DST
Run Code Online (Sandbox Code Playgroud)
(另一种方法是使用选项全局模拟标准外壳行为-o shwordsplit......)
从联机帮助页:
[in
zsh] 中常见的一个区别是,替换到命令行上的变量不会拆分为单词。见外壳选项的说明SH_WORD_SPLIT在部分“参数扩展”zshexpn(1)。在 中zsh,您可以显式请求拆分(例如${=foo}),也可以在希望将变量扩展为多个单词时使用数组。请参阅 中的“数组参数”部分zshparam(1)。
Gil*_*il' 10
问题不是来自$EXCLUDE,而是来自$OPTS。您的脚本依赖于发生在$OPTS. 这是一个坏主意; 例如,如果您更改$EXCLUDE为包含模式并--exclude=$EXCLUDE匹配当前目录中的文件,或者更改$EXCLUDE为包含空格,则它将失败。
$OPTS是一个单词列表,而不是一个单词。如果您只需要您的脚本在 ksh、bash 和 zsh 中工作,请将其设为数组:
SRC="/path_to_source"
DST="/path_to_dest"
EXCLUDE=".hg"
OPTS=(-avr --delete --progress --exclude="$EXCLUDE" --delete-excluded)
rsync "${OPTS[@]}" "$SRC" "$DST"
Run Code Online (Sandbox Code Playgroud)
如果您只想让脚本在 zsh 中工作,您可以简化最后一行:
rsync $OPTS $SRC $DST
Run Code Online (Sandbox Code Playgroud)
如果您希望脚本在每个 shell 中工作,您需要使用位置参数。它们是唯一可用的阵列。
set -- -avr --delete --progress --exclude="$EXCLUDE" --delete-excluded
rsync "$@" "$SRC" "$DST"
Run Code Online (Sandbox Code Playgroud)
如果您有一个 shell 脚本,并且希望能够方便地与 zsh 一起运行,请将这一行放在开头——它告诉 zsh 像 ksh 一样运行,并且它在其他 shell 上是无操作的。
emulate ksh >/dev/null 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
要完成 St\xc3\xa9phane Gimenez 答案(我还不能发表评论),一种解决方案是通过检查您是否正在使用zsh然后将脚本转换$OPTS为这样的数组,使脚本可移植到 bash
[ -n "${ZSH_VERSION:-}" ] && set -A OPTS ${=OPTS}\nRun Code Online (Sandbox Code Playgroud)\n\n然后你的 rsync 命令就可以工作了。
\n