QA@IT

様々な環境で使える、コマンド(実行ファイル)を見つける方法を知りたい

3664 PV

複数の環境で以下の同じ.zshrcを共有して使用しています。
https://github.com/iwadon/dotfiles/blob/master/.zshrc
.zshrcでは、それぞれの環境で特定のコマンド(実行ファイル)の有無によって設定する内容を分けたりしています。
しかし、過去に幾つかの方法を試しましたが、どの方法も一長一短です。何かよりよい方法はありますでしょうか?

まず、以下のような前提があります:

  • 必要なコマンドが実行可能かどうかを確認したい。
  • shellはzsh。
  • PATHは事前に設定済み。
  • 正しく見つかった場合のコンソールへの出力はできれば無くしたい(無闇な/dev/nullへの出力も避けたい)。
  • Mac OS X、FreeBSD、Cygwinの各環境で同じ.zshrcを使いたい。

次に、私が試した方法を挙げます:

which -s xxx
  • BSD系の/usr/bin/whichならばOK。
  • zshのビルトインコマンドでは-sが別の意味となり、かつ出力を抑える方法がない。
  • Cygwinの/bin/whichには-sが無く、上記同様出力を抑える方法がない。
  • -s を付けなければ想定する全環境で使えるが、コマンドが存在してもしなくても出力されるメッセージが長すぎる。
test -x =xxx
  • コマンドが存在する場合にはOK。
  • コマンドが存在しない場合その行でエラーとなり、.zshrcの次の行以降が処理されない。
whence xxx
  • 想定している全環境で使用可能。
  • 出力を抑える方法はないが、出力内容がwhichよりコンパクト。

なお、現状はwhenceを使用していますが、他の方法よりマシという理由から採用してまして、まだ満足はできてません。
ログインする度に見つかったコマンド名が数個羅列されるのを見る度になんとかならいないものかと考えてしまいます。

何か他によりよい方法はありますでしょうか?

回答

/dev/null への出力を避けて、エイリアスや関数にも対応するとなるとちょっとくどいですが

if [[ -x `whence -p hoge` ]]; then
  #処理
fi
[[ -x `whence -p hoge` ]] && #処理

とかどうでしょう?

編集 履歴 (0)
  • 回答ありがとうございます。
    残念ながら、whenceはzshのビルトインコマンドなので`~`の中では使えないようです。
    -
  • OSX 10.7(zsh 4.3.17)、Debian 6.0.5(zsh 4.3.10)、Ubuntu 12.04(zsh 4.3.17)で確認したところTerminalからの実行・.zshrcへの記入共に使えたのですがCygwinとかだと違うのかな…… -
  • oh-my-zshのarchlinux.plugin等でもshell builtinなwhichで同じような条件を書いているようなので、ビルトインコマンドだからってことはないような気もします。
    https://github.com/robbyrussell/oh-my-zsh/blob/master/plugins/archlinux/archlinux.plugin.zsh
    -
  • すみません。先のノートは回答を読んでつい`which -p ls`だけを試してlsの結果が表示されたため、「which -p が無視されて ls が実行されてしまった」と勘違いしてしまいました。
    いただいた回答で目的を達成できそうです。とくに [[ ~ ]] は初めて知りました。ありがとうございました。
    -
  • 上記which -pはwhence -pの間違いです。失礼しました。あと oh-my-zsh へのリンクありがとうございました。参考にしたいと思います。 -

自分の好きなように which -s command 相当を作ればいいだけのような。

which-s() { whence -p ${1+"$1"} >/dev/null; }

if which-s foo; then
  : foo コマンドがある場合の処理
fi

if which-s bar; then
  : bar コマンドがある場合の処理
else
  : bar コマンドがない場合の処理
fi

which-s baz && : baz コマンドがある場合の処理
which-s baz || : baz コマンドがない場合の処理
編集 履歴 (3)
  • 回答ありがとうございます。
    記述を完結にするためfunctionにまとめるのはアリだと思います。
    -

whenceの終了ステータスを見るのがよくある手かと思います。

if whence hoge > /dev/null; then
    # ある場合の処理
else
    # ない場合の処理
fi
編集 履歴 (0)
  • 回答ありがとうございます。
    /dev/nullへの出力を避けられない場合にはそうしたいと思います。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。