一尘不染

如何从 Bash 脚本中检查程序是否存在?

javascript

我将如何验证程序是否存在,以返回错误并退出或继续执行脚本的方式?

看起来应该很容易,但它一直困扰着我。


阅读 205

收藏
2022-01-29

共1个答案

一尘不染

POSIX 兼容:

command -v <the_command>

示例使用:

if ! command -v <the_command> &> /dev/null
then
    echo "<the_command> could not be found"
    exit
fi

对于 Bash 特定环境:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

解释

避免which。它不仅是您启动的一个外部进程,只需要做很少的事情(hash意味着typecommand.系统到系统。

为什么关心?

  • 许多操作系统都有一个甚至没有设置退出状态,这意味着它which甚至不会在那里工作并且总是会报告它存在,即使它不存在(请注意,一些 POSIX shell 似乎也这样做)。if which foo``foo``hash
  • 许多操作系统会which做一些自定义和邪恶的事情,例如更改输出甚至挂钩到包管理器。

所以,不要使用which. 而是使用其中之一:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(小旁注:有些人会建议2>&-相同2>/dev/null但更短 -这是不正确的2>&-关闭 FD 2 会在程序尝试写入 stderr 时导致错误,这与成功写入并丢弃输出非常不同(而且很危险!))

如果您的哈希爆炸是/bin/sh那么您应该关心 POSIX 所说的内容。typeandhash的退出代码没有被 POSIX 很好地定义,并且hash当命令不存在时可以看到成功退出(还没有看到这个type)。 command的退出状态由 POSIX 明确定义,因此使用起来可能是最安全的。

但是,如果您的脚本使用bash,POSIX 规则就不再重要了,并且两者都可以type完全hash安全地使用。type现在有一个-P只搜索PATH并且hash具有命令的位置将被散列的副作用(以便下次使用它时更快地查找),这通常是一件好事,因为您可能会检查它的存在以便实际使用它.

gdate作为一个简单的例子,这是一个如果存在则运行的函数,否则date

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

具有完整功能集的替代方案

您可以使用scripts-common来满足您的需求。

要检查是否安装了某些东西,您可以执行以下操作:

checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."
2022-01-29