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更便宜),你也可以依靠内置实际做你想要的,而外部命令的效果可以容易因系统而异。
为何关心?
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 时导致程序出错 ,这与成功写入并丢弃输出(并且危险!)非常不同
如果你的哈希爆炸是/bin/sh那么你应该关心 POSIX 所说的。 POSIX 没有非常好地定义type和hash的退出代码,并且当命令不存在时, 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
}
以下是检查$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 标准。 [ 错误报告 ] [ 标准 ]
此外,如果您要查找的命令已被定义为别名,则此操作将失败。
我同意 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不是。