${@} 作为命令的 Bash 扩展

${@} 作为命令的 Bash 扩展

我有一个父脚本

while read cmd 
do
  nohup ./script ${cmd[@]} &>> log &
done < ~/list 

执行这个子脚本

while true
do 
  eval "${CMD[@]}"
  #${CMD[@]}
  #./panic
done

与这个命令列表

node ~/www/splash/app.js
node ~/www/splash-two/app.js

当子脚本调用时,eval ${CMD[@]}它会按照我期望的方式运行该命令,没有任何抱怨,但是当我尝试删除 eval 并使用${CMD[@]}它运行命令时,会抛出错误:

Error: Cannot find module '/home/rumplefraggle/SYS/RABBOT/~/www/splash/app.js'

现在我认为这可能与节点命令有关,所以我尝试
ls ~
作为命令执行,但它抛出了~无法找到的错误。

回显${@}而不运行它会像我期望的那样扩展。

另外,手动将命令插入子脚本中也可以按预期工作

我不明白为什么eval有效并且简单地使用命令运行${@}却不起作用。是什么原因导致${@}无法扩展~

${@}为什么节点在使用时将目录名称附加到命令中?

答案1

这是因为波形符扩展。 eval 扩展波浪号,将其替换为主目录的完整路径。如果没有它,该命令将获取传递的文字波形符,并尝试使用相对路径(不存在)。

$ echo ~
/home/chris
$ echo "~" 
~
$ eval 'echo ~' 
/home/chris 

答案2

您需要报价:"${cmd[@]}"

如果没有引号,数组的所有元素都会被压缩成一个字符串。使用引号,每个元素都将被单独正确处理。

手册:

如果下标‘@’or ‘*’,该词扩展到数组的所有成员姓名。仅当单词出现在双引号内时,这些下标才会有所不同。如果该词被双引号括起来,[...] ${name[@]}将名称的每个元素扩展为单独的单词。

相关内容