我正在尝试编写所有sh
启动/环境脚本以尽可能多地使用干燥并尽可能多地:“适用于我将其克隆到的每个 *nix”。这意味着确保如果我尝试运行不存在的代码,该代码会正常失败。为此,我需要能够测试程序是否存在。我知道如何测试文件是否存在,但我不确定如何测试应用程序在路径中是否可执行。我宁愿使用 $PATH,因为其中一些需要在 arch、ubuntu 和 centos 上工作。有些可能安装在我的主目录中,在我没有 root 的系统上,其他可能不会安装,还有一些可能安装在系统路径中。
答案1
使用type commandname
。如果有任何可执行文件,则返回 true commandname
:别名、函数、内置或外部命令(在 中查找$PATH
)。或者,使用command commandname
commandname
如果是内置或外部命令(在 中查找),则返回 true $PATH
。
exists () {
type "$1" >/dev/null 2>/dev/null
}
有一些 sh 变体(绝对是 POSIX 之前的;我知道/bin/sh
在 OSF1 ≤3.x 下以及早期 NetBSD 版本和一些 20 世纪 Linux 发行版中发现的 Almquist shell 的某些版本)总是type
返回 0 或不返回存在。我认为本世纪没有任何系统附带这些。如果您遇到过它们,您可以使用以下功能来$PATH
手动搜索:
exists () { (
IFS=:
for d in $PATH; do
if test -x "$d/$1"; then return 0; fi
done
return 1
) }
如果您想排除内置函数和函数并在$PATH
.大多数 shell 都有一个内置的功能,command -v
,尽管它是 POSIX 的一个相对较新的补充(从 POSIX:2004 开始仍然是可选的)。它基本上是 的程序员友好版本type
:它打印 中可执行文件的完整路径$PATH
、内置函数或函数的裸名称以及别名的别名定义。
exists_in_path () {
case $(command -v -- "$1") in
/*) return 0;;
alias\ *) return 1;; # alias
*) return 1;; # built-in or function
esac
}
Ksh、bash 和 zsh 也必须type -p
仅查找$PATH
.注意,在 bash 中,如果是内置 or 函数,则返回状态type -p foo
为 0 ;foo
如果您想测试 中的可执行文件$PATH
,则需要检查输出是否不为空。type -p
不在 POSIX 中;例如 Debian 的 ash(在/bin/sh
Ubuntu 上)就没有它。
答案2
如果您只是寻找外部程序,也可以使用which。但不知道它有多便携。