无法弄清楚如何修复shellcheck投诉,我不应该在从另一个脚本启动一个脚本时使用glob作为命令

时间:2018-02-27 17:13:00

标签: bash glob shellcheck

示例脚本:

#!/bin/bash

printf '1\n1\n1\n1\n' | ./script2*.sh >/dev/null 2>/dev/null

Shellcheck返回以下内容:

In script1.sh line 3:
printf '1\n1\n1\n1\n' | ./script2*.sh >/dev/null 2>/dev/null
                        ^-- SC2211: This is a glob used as a command name. Was it supposed to be in ${..}, array, or is it missing quoting?

根据https://github.com/koalaman/shellcheck/wiki/SC2211,此规则应该没有例外。

具体来说,它建议"如果你想通过glob指定一个命令名,例如在./myprogram-*/foo中没有硬编码版本,首先扩展到数组或参数以允许处理0或2+匹配的情况。"

我首先使用glob的原因是我将日期追加或更改为我刚创建或更改的任何脚本。有趣的是,当我使用" bash script2 * .sh"而不是" ./ script2 * .sh"投诉消失了。

我是否解决了问题,或者我在欺骗shellcheck而忽略了一个不应忽略的问题?如果我使用错误的bash语法,我怎样才能执行另一个需要使用glob 以正确方式引用的脚本?

1 个答案:

答案 0 :(得分:1)

问题在于./script2*.sh最终可能会运行

./script2-20171225.sh ./script2-20180226.sh ./script2-copy.sh

这是一个奇怪的,可能是无意的事情,特别是如果脚本被这些参数混淆,或者你想要使用最新的文件。你的"修复"有同样的根本问题。

您提到的建议采用以下形式:

array=(./script2*.sh)
[ "${#array[@]}" -ne 1 ] && { echo "Multiple matches" >&2; exit 1; }
"${array[0]}"

并防范这个问题。

由于您似乎假设您只有一个匹配的文件只能在没有参数的情况下调用,您可以将其转换为函数:

runByGlob() {
  if (( $# != 1 ))
  then
    echo "Expected exactly 1 match but found $#: $*" >&2
    exit 1
  elif command -v "$1" > /dev/null 2>&1
  then
    "$1"
  else
    echo "Glob is not a valid command: $*" >&2
    exit 1
  fi
}

whatever | runByGlob ./script2*.sh

现在,如果您有零个或多个匹配文件,它将中止错误,而不是使用奇怪的参数运行错误的文件。