在Bash脚本中检测命令未找到

7

我有一系列需要执行的命令。然而,每当出现“command is not found”错误时,我都需要退出。因此,执行后检查输出不是一个选项。

当“command is not found”和成功时,“$?”变量等于零。


可能是重复的问题:从Bash脚本中检查程序是否存在 - blong
4个回答

8

如果需要从脚本中完成这项任务,自然要使用条件语句来表达这种行为:

asdf 2> /dev/null || exit 1

这实际上是最简单和最清晰的方法,谢谢。 - GoTTimw
ls /this/file/does/not/exist 2>/dev/null 怎么样? ls 命令仍然存在。 - anishsane
@anishsane 当然可以。没有人说这会排除其他命令失败的情况。 - user1019830
+1!我不知道即使被调用的程序不存在也能工作。谢谢! - TrueY

6
如果找不到命令,则退出状态应为127。然而,您可能正在使用bash 4或更高版本,并定义了一个名为command_not_found_handle的函数。如果找不到命令,则会调用此函数,并且它可能会退出0,掩盖127代码。
运行type command_not_found_handle将显示该函数的定义(如果已定义)。您可以通过运行unset command_not_found_handle来禁用它。

2
更新:
尝试
[ -x "$executable" ] && echo "Command '$executable' not found" >&2 && exit 1

这将向 stderr 写入一个错误并以 1 的退出码退出。
如果您只知道实用程序的名称,可以使用内置命令 type 检查其路径。
例如:
type type
type ls
type xls

输出:

type is a shell builtin
ls is /usr/bin/ls
./test.sh: line 13: type: xls: not found

如果未找到实用程序,则测试返回1。

所以如果 $executable 可以是任何东西(内置、别名、二进制文件等),则可以使用以下代码:

type -p ls>/dev/null && ls -l
type -p xls>/dev/null && xls --some_arg

这将运行ls(任何可执行文件),但不会运行xls。
无论如何,如果在脚本中未设置execfail选项(shopt),则脚本将在声明bash:some_utility:command not found错误消息后退出。 如果设置了此选项,则继续进行。 但是,您可以trap伪信号ERR并执行所需操作:
shopt -s execfail
fnc() { echo $?, $_, Oops;}
trap fnc ERR

ls -d *|head -2
xls
yls

输出:

a1
a2
./test_tLcn.sh: line 8: xls: command not found
127, xls, Oops
./test_tLcn.sh: line 9: yls: command not found
127, yls, Oops

2
只有当$executable是您要查找的可执行文件的路径时,此方法才有效。-x不会执行路径查找。 - chepner
@chapner:你说得对!它无法检测内部bash命令。可以使用例如type来完成。 - TrueY
@chapner:根据您的评论,我更新了我的答案。请看一下! - TrueY
捕获“ERR”似乎过于宽泛,因为该函数将在任何错误上运行,而不仅仅是命令未找到的错误。 - chepner
@chepner:是的。但如果 $? 的值是 127,那么就可以检测到发生了“命令未找到”错误。可以使用 $_ 来打印未找到的实用程序名称。 - TrueY

0
jq 为例:
jq --version || echo "Please install [jq](https://stedolan.github.io/jq/download) first." &&  exit 1

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