2

示例脚本:

#!/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 的脚本?

4

1 回答 1

2

问题在于它./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

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

于 2018-02-27T21:39:07.120 回答