从Bash脚本检查程序是否存在
我将如何验证程序是否存在,以何种方式返回错误并退出,还是继续执行脚本?
它似乎应该很容易,但它一直困扰着我。
回答
兼容POSIX:
command -v <the_command>
对于bash
特定的环境:
hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords
说明
避免which
。 它不仅仅是一个外部过程,你只需要做很少的事情(意思是像hash
, type
或command
这样的内建hash
便宜),你也可以依靠内建函数来实际执行你想要的操作,而外部命令的影响可以从系统到系统很容易变化。
为什么在意?
which
甚至不设置退出状态 ,这意味着if which foo
甚至不会在那里工作,并会始终报告foo
存在,即使它没有(请注意,一些POSIX外壳表面上做这也是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这会导致错误的程序,这与成功写入并丢弃输出(和危险!)非常不同)
如果你的hash bang是/bin/sh
那么你应该关心POSIX的说法。 type
和hash
的退出代码不是由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
}
我同意lhunath不鼓励使用which
,而且他的解决方案对于BASH用户来说是完全有效的。 但是,为了更便于携带,应该使用command -v
代替:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
命令command
符合POSIX标准,请参阅此处的规范:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html
注意: type
是POSIX兼容的,但是type -P
不是。
以下是检查命令是否存在于$PATH
且可执行的可移植方式:
[ -x "$(command -v foo)" ]
例:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
可执行检查是必需的,因为如果在$PATH
找不到具有该名称的可执行文件,bash将返回一个不可执行文件。
还要注意,如果在$PATH
早些时候存在与可执行文件同名的不可执行文件,则即使后者将被执行,破折号也会返回前者。 这是一个错误,违反了POSIX标准。 [错误报告] [标准]
另外,如果您正在查找的命令已被定义为别名,则这将失败。
链接地址: http://www.djcxy.com/p/1673.html