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

标签 bash

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

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

最佳答案

回答
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 .它不仅是您为做很少的事情而启动的外部进程(意味着像 hashtypecommand 这样的内置程序更便宜),您还可以依靠内置程序来实际做您想做的事情,而外部命令的效果很容易因系统而异。
为什么关心?
  • 许多操作系统都有 which甚至没有设置退出状态 , 表示 if which foo甚至不会在那里工作并且会总是 报告 foo存在,即使它不存在(请注意,一些 POSIX shell 似乎也为 hash 执行此操作)。
  • 许多操作系统使which做一些自定义和邪恶的事情,比如改变输出,甚至 Hook 到包管理器。

  • 所以,不要使用 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所说的。 typehash的退出代码并没有被 POSIX 很好地定义,hash当命令不存在时,可以看到成功退出(在 type 中还没有看到)。 command的退出状态由 POSIX 明确定义,因此使用起来可能是最安全的。
    如果您的脚本使用 bash不过,POSIX 规则不再重要,typehash变得完全安全使用。 type现在有一个-P只搜索 PATHhash具有命令的位置将被散列的副作用(以便下次使用它时更快地查找),这通常是一件好事,因为您可能会检查它的存在以便实际使用它。
    举个简单的例子,下面是一个运行 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."
    

    关于bash - 如何从 Bash 脚本中检查程序是否存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71953175/

    相关文章:

    Linux Bash 自动命令,源文本文件

    linux - 根据 AWS "--profile"更改用户的命令提示符颜色

    linux - 文件删除后进程继续保留文件

    linux - 后台 Bash 脚本 : how to kill child processes

    php - SED 命令 : won't insert the string I want

    bash - 从 MATLAB 调用 Anaconda 环境 : Conda Command Not Found

    bash - 我想删除322个文件名的前8个字符

    bash - 全局变量值未在 shell 脚本中的函数内设置

    linux - 如何在 bash 中使用日期动态更改天数

    bash - Node.js 生成和 `*` 用于选择多个文件