whichコマンドで条件判定をする際の注意事項

Table of Content

活用シーンのイメージ

  • コマンドが使える場合は処理Aを、コマンドが使えない場合は処理Bをさせたい。
  • あるいは、処理をスキップさせたい。

こういった場合、whichコマンドで判定しようとすると失敗する ので、対策を考える必要がある。
要はコマンドが使えるかどうかを調べたいので「コマンドを実行した結果を取得する」のではなく、「コマンドを実行した状態を取得する」すればよい。

以下、コード

やりたいイメージ(失敗する)

if [ -z "$(which 'コマンド' | grep 'コマンド not found')" ];then
  # 処理したい内容
fi

解決策1

コマンド 2>/dev/null
if [ "$?" -eq 127 ];then
  # 処理したい内容
fi

とりあえずこれで動くが、正しいコードではない。

解決策2

実はこれで動く。

if [ -z "$(which コマンド) ];then
  # 処理したい内容
fi

which コマンドを実行すると「コマンド not found」とエラーメッセージが表示されるため、失敗判定をgrepで取得したくなるが、やる必要はない。

なぜこうなるのか?

ターミナルから実行しているwhichと、スクリプトファイル内から実行しているwhichが異なるため。

検証

# ターミナルで実行
which which
# which: shell built-in command
# shellファイルで実行した場合
sh which_test.sh
# /usr/bin/which

### which_test.shの内容は、コマンドと同じく`which which`のみ

となり、同じwhichでも異なる事が分かる。
ここでShellと同様に`/usr/bin/which`で実行すると同じ結果が得られる。

結論

エラーメッセージを出しながら出力結果を弄らない辺り、ビルトインのコマンドの方が優秀だと感じるが、これのせいで混乱してしまったので備忘録にする。

シェアする