怎样使用bash判断二进制文件是否已安装?

7

使用终端,最简单的方法是确定用户系统上是否安装了名为dcmdump的二进制文件。如果已安装,我需要知道它的位置(例如/usr/local/bin),如果未安装,则希望终端回显FALSE

我对终端脚本知之甚少,但输入以下内容:

command -v dcmdump

输出dcmdump安装的目录(如果已安装-非常好),但如果没有安装,则不会输出任何内容(我希望它输出字符串 FALSE


2
但如果没有回显,则表示未安装” - 这就是您可以知道它未安装的方式。为什么打印FALSE更有用?顺便说一下,终端只是一个终端枚举器;它只允许您输入和显示文本。它是 shell 提供了实际执行操作的能力。 - Keith Thompson
1
你打算在命令已安装的情况下运行它吗?如果是这样,最简单的方法就是尝试运行它,如果退出状态为126或127,则告诉用户安装它并退出。 - chepner
4个回答

9
您可以使用以下内容:
$ which dcmdump 2>/dev/null || echo FALSE

这是工作原理:
  • 整个表达式是两个命令的布尔或(使用||表示)。左侧是命令which dcmdump 2>/dev/null,右侧是echo FALSE
  • 由于采用了惰性求值(或短路),如果左侧求值为“真”(或“成功”),则不会评估右侧。否则,会评估右侧。
  • 命令which NAME在当前shell的$PATH中查找名为NAME的可执行文件。如果找到一个,它将其绝对路径打印到标准输出并退出状态指示“成功”,否则,它可能会或可能不会将错误消息打印到标准错误输出,并返回表示“失败”的状态。
  • 由于我们不想要which的错误消息,而是想要自己的,因此我们使用2>/dev/nullwhich的标准错误输出重定向到黑洞/dev/null
  • 命令echo TEXT只是将TEXT输出到标准输出。如果您希望将FALSE打印到标准错误输出,则可以使用echo FALSE >&2进行重定向。

6
在至少OS X系统上,执行which dcmdump命令,使其返回/usr/local/bin/dcmdump(如果找到该命令)不是完全错误的。但在其他环境中使用which命令可能会有问题
但总体上,反对使用which命令的主要原因是它是一个单独的命令,而不是内置于shell中的,所谓的shell“builtins”是更好的选择,当它们可以像which一样完成任务时。
因此,如果您只想检查命令是否存在(而不需要知道其位置),则可以使用hash dcmdump内置命令,并检查返回值;例如:echo $?或:
if hash dcmdump 2>/dev/null; then
  echo "OK, you have dcmdump installed. We’ll use that."
else
  echo "You need dcmdump. I can install if for you, OK?"
  read -e -p "Y or N? " yn
  if [[ "y" = "$yn" || "Y" = "$yn" ]]; then
    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    brew install dcmtk
  else
    echo "We need dcmdump. Stopping."
    exit
  fi
fi

对于检查命令是否存在的选项,没有一个返回字面字符串FALSE(正如您在问题中所要求的)。但是使用hash dcmdump并检查返回值即可完成工作。

如果您确实想知道命令的确切位置,那么command -v就可以给您。使用type dcmdump也会以稍微不同的形式提供该信息。

无论如何,hashcommand -vtype都是shell内置命令,因此它们被推荐用于此,而不是which SO上的规范答案提供了更多细节。

顺便说一句,如果您的目标是在系统上获得dcmdump,则可以通过安装homebrew来实现:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

然后在此之后,您可以安装dcmtk软件包:

brew install dcmtk

然后您将在/usr/local/bin/dcmdump中拥有一个dcmdump命令。


我在 Stack Overflow 上看到使用 which 命令不是一个好主意,因此我认为 command -v 方法更好。问题是,我不知道如何在终端中编写 if...else 语句。 - Garry Pettet
啊,关于那个问题,实际上使用 hash 是最好的。我会更新我的答案。 - sideshowbarker
感谢您关于获取DCMTK的解释-昨天我弄明白了(花了很长时间!)。实际上,我需要一种方法来检查用户是否已在其系统上安装了DCMTK(如果没有,则我的应用程序将提示他们)。 - Garry Pettet

1
"POSIX 兼容:"
command -v dcmdump || echo FALSE

或者如果您需要重复使用路径,请使用以下内容。
if cmd=$(command -v dcmdump); then echo $cmd; else echo FALSE; fi

1
你可以使用 which 并检查返回值是否为 null,如下所示:
#!/bin/sh
bi=$(which $1)
if [ -z $bi ]
then
    echo "FALSE"
else
    echo $bi
fi

然后可以像这样运行脚本:

./script command


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接