如何将命令及其参数作为单个参数传递给脚本?

How to pass command with its arguments as a single argument to script?

我有一个用于构建内核的脚本,其中有一个函数,我想用它来捕获构建命令中的错误,但我不知道如何将多个参数作为一个参数传递给让它正常工作。语法如下:

run_build() {
cmd=$()
status=${PIPESTATUS[0]}
$*
if ($status != 0); then
    echo "$cmd failed!"
    exit 1
else
    echo "$cmd succeeded."
fi
}

问题是,当我尝试传递带有参数的 make 命令时,make 命令在没有参数的情况下执行。我尝试使用“$*”语法来调用所有参数,但它似乎不起作用。一个示例命令是

make O=out -j8 zImage

从脚本调用该行时,我需要包含接下来的 3 个参数。有人有想法吗?

首先,您不想将整个命令作为单个参数传递:I'm trying to put a command in a variable, but the complex cases always fail!

这是主要错误:cmd=$() -- $() 语法调用 Command Substitution 执行 第一个参数。只需使用 cmd= 将第一个参数存储到 "cmd" 变量中。

其他错误:

  • if ($status != 0); then -- 该语法不正确:使用 if ((status != 0)); then 进行正确的算术计算。
  • $* -- 要正确执行位置参数,请使用 "$@"(带引号)-- 该形式将按预期保留任何包含空格的参数。

正确的解决方案可能是这样的

if "$@"; then
    echo "$@ succeeded" >&2
else
    rc=$?
    echo "$@ failed" >&2
fi

但这看起来仍然像是在用更糟糕的东西替换非常好的内置功能。

不喜欢这个设置有几个明显的原因,也有一些不那么明显的原因。

郑重声明,c.f。 this page on why not to do this.
同样值得注意的是,如果你转向 eval,这在理论上就是这个函数正在做的事情......please read this too

...但对于一个简单的解决方案 -
参数以数组形式出现。如果您正在 运行ning 构建,则使您的函数 运行 成为构建,使用 quoted 参数。

run_build() {
  if make "$@"  # QUOTED, *explicit* call to make
  then echo "'make $@' succeeded."
  else echo "'make $@' failed."
       return 1 # exit in function only sets return - be explicit
  fi
}

run_build O=out -j8 zImage # run_build as a make synonym

不要尝试构建无所不能的函数。
那就是疯狂。

如果您必须使用除 make 以外的其他命令,请验证并验证。

run_build() {
  local cmd=
  shift
  case "$cmd" in
  make|or|some|other|specifically|ok|word)
    if "$cmd" "$@" # QUOTED!!!
    then echo "'$cmd $@' succeeded." 
    else echo "'make $@' failed."
         return 1 
    fi 
  ;;
  *) echo "Invalid argument: '$cmd' not recognized."
     return 1
  ;;
  esac
}

如果您至少没有这样做,那么该功能的目的是什么?我的意思是,无论如何你都在传递命令的所有部分,除了执行它们之外没有对它们做太多事情。为什么不只是......你知道,执行它们,而不是为功能而烦恼?但即使你保持最简单,引用,引用,引用。

run_build() { "$@" && echo "'$@' succeeded" || {
                      echo "'$@'failed; return 1; }; }