如何测试以查看$ PATH中是否存在应用程序?


19

我正在尝试编写所有sh启动/环境脚本,以使用尽可能多的DRY和尽可能多的DRY:“可在我将其克隆到的每个* nix上使用”。这意味着确保如果我尝试运行不存在的代码,则代码会正常运行。为此,我需要能够测试程序是否存在。我知道如何测试文件是否存在,但是我不确定如何测试应用程序在路径内是否可执行。我宁愿使用$ PATH,因为其中一些需要在arch,ubuntu和centos上工作。有些可能安装在我的root目录中,没有我的系统上,有些可能没有安装,还有一些我安装在系统路径中。


2
这样的答案就是我为此类问题添加的书签。
2012年

Answers:


19

使用type commandname。如果commandname可以执行任何命令,则返回true :别名,函数,内置命令或外部命令(在中查找$PATH)。另外,command commandname如果commandname是内置命令或外部命令(在中查找$PATH),请使用use 返回true 。

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
) }

如果要排除内置函数和函数并在中查找名称,则此函数通常很有用$PATHcommand -v尽管这是POSIX的相对较新的功能,但大多数Shell对此都有内置功能(从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中,type -p foo如果foo是内置函数或函数,则返回状态为0;否则,返回状态为0 。如果要在中测试可执行文件$PATH,则需要检查输出是否为空。type -p不在POSIX中;例如Debian的灰烬(/bin/sh在Ubuntu上)没有。


@gilles,这(或类似的东西)if [ type keychain ]; then行不通吗?我收到错误消息,/home/xenoterracide/.zshrc:84: parse error: condition expected: type我想我可以编写该函数存在了……我只是觉得这在某种意义上可能会更简单……
xenoterracide 2010年

@xenoterracide:放括号!
吉尔(Gilles)'所以

我认为您正在寻找if type $APP >/dev/null 2>/dev/null; then ...不需要[]
史蒂文D 2010年

4
ah,我知道我应该精神焕发。再次被吉尔斯击败!
史蒂文D 2010年

type -p如果您专门在寻找命令$PATH(不是别名,函数或内置函数)。
短暂的2011年

1

如果您只在寻找外部程序,则也可以使用它。不知道那有多便携。


3
从理论上讲,它不如typeor 便携commandwhich例如,不在POSIX中。实际上,which确实存在无处不在,但是在某些地方(将其实现为csh脚本),它使用了不同的路径(由于导致.cshrc),这违背了目的。
吉尔斯(Gillles)“所以-别再作恶了”
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.