web-dev-qa-db-ja.com

$ PATHにアプリケーションが存在するかどうかを確認するにはどうすればよいですか?

私はすべてのsh起動/環境スクリプトを記述して、[〜#〜] dry [〜#〜]と動作するようにしています。 * nix可能な限りクローンします。つまり、そこにないコードを実行しようとすると、コードが正常に失敗することを確認します。そのためには、プログラムが存在するかどうかをテストできる必要があります。ファイルが存在するかどうかをテストする方法は知っていますが、パス内でアプリケーションが実行可能かどうかを確認するためのテスト方法がわかりません。これらのいくつかはArch、ubuntu、centosで動作する必要があるため、私はむしろ$ PATHを使用します。 rootがないシステムのホームディレクトリにインストールされているもの、インストールされていないもの、システムパスにインストールされているものがあります。

19
xenoterracide

type commandname を使用します。これは、commandnameが実行可能である場合はtrueを返します:エイリアス、関数、組み込みコマンド、または外部コマンド($PATHで検索)。または、 command commandname を使用します。これは、commandnameが組み込みコマンドまたは外部コマンド($PATHで検索)の場合にtrueを返します。

exists () {
  type "$1" >/dev/null 2>/dev/null
}

いくつかのshバリアントがあります(確かにPOSIXより前です。OSF1≤3.xの下で/bin/shを知っています。また、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で名前を検索する場合に一般的に役立ちます。ほとんどのシェルには、組み込みの 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では、fooが組み込み関数または関数の場合、type -p fooの戻りステータスは0です。 $PATHで実行可能ファイルをテストする場合は、出力が空でないことを確認する必要があります。 type -pはPOSIXにはありません。たとえば、Debianの灰(Ubuntuでは/bin/sh)にはありません。

外部プログラムのみを探している場合は、それを使用することもできます。しかし、それがどれほどポータブルであるかはわかりません。

1
Kim