which について
whichは、コマンドの確認や解決に`which`ではなくPOSIXの`command -v`を使うよう案内する、シェル向けのエージェントスキルです。移植性の違いや置き換え方、パスを明示的に扱うケースを説明します。
主な機能
- 01コマンド確認を`command -v`に置換
- 02シェル間の移植性の違いを説明
- 03無出力とエラー表示の確認方法
- 04コマンド名とファイルパスを区別
- 05`$PATH`内の実行可能ファイル一覧に対応
活用シーン
- 01コマンドの利用可否を確認
- 02外部実行ファイルのパスを解決
- 03シェルコードやビルド手順を点検
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ petr-korobeinikov/ skills --skill whichインストール後、Claude Code で/whichを入力して読み込まれたか確認します。
詳細
which
コマンドの有無を確認したり、そのパスを表示したりするために、whichは決して使わないでください。
代わりにcommand -vを使ってください。
理由
command -vはPOSIXで必須とされているシェル組み込みコマンドです (bash、zsh、dash、ash、ksh、busybox sh)。whichは外部プログラムであり、 存在しない場合や、 エイリアスに置き換えられている場合、 またはシェル関数に置き換えられている場合があります。whichの動作は実装によって異なります。 BSD、GNU、Debianのシェルスクリプト版which、zshの組み込み版、 busyboxのアプレットでは、 オプション、 出力形式、 終了コードが異なります。command -vは、シェル組み込みコマンド、 関数、 エイリアスも報告します。$PATH上のファイルだけではありません。 これは通常、呼び出し元が実際に求めている動作です。command -vは、名前が見つからない場合に 信頼できるゼロ以外の終了コードを返し、 標準出力にも標準エラー出力にも何も出力しません。
直接置き換える場合
| 使わないでください | 代わりに使ってください |
|---|---|
which foo | command -v foo |
which foo >/dev/null 2>&1 | command -v foo >/dev/null |
if which foo; then … | if command -v foo >/dev/null; then … |
名前が見つからない場合、command -vは標準エラー出力に何も書き込まないため、
2>&1は不要です。
1行で置き換えられず、以下のイディオムが必要なケースが2つあります。
path=$(which foo)—command -vはファイルシステム上のパスではなく、組み込みコマンド名やエイリアス文字列を返す場合があります。which -a foo—command -vが解決するのは最初に見つかったものだけです。
イディオム
存在確認(出力なし):
if command -v foo >/dev/null; then
# ...
fi
明確な失敗メッセージを表示する存在確認:
command -v foo >/dev/null || {
echo "foo is required but not installed" >&2
exit 1
}
ファイルシステム上のパスを解決する:
foo_path=$(command -v foo) || {
echo "foo not found" >&2
exit 1
}
case "$foo_path" in
/*) ;;
*) echo "foo is not an external binary (got: $foo_path)" >&2
exit 1 ;;
esac
command -vの出力は次のいずれかです。
/usr/bin/foo—$PATH上の外部ファイル。foo— シェル組み込みコマンドまたは関数。alias foo='…'— エイリアス。
/*のガードは最初の形式だけを受け入れます。
エッジケース
-
$PATH上のすべての一致を一覧表示する(which -a) ための、単一の呼び出しで済むPOSIX準拠の同等手段はありません。$PATHを明示的に走査してください。( IFS=: for dir in $PATH; do candidate=${dir:-.}/foo [ -f "$candidate" ] && [ -x "$candidate" ] && printf '%s\n' "$candidate" done )[ -f ]と[ -x ]を組み合わせると、通常の実行可能ファイルだけに絞り込めます。 これはwhich -aが報告する内容と一致します。[ -x ]だけでは、実行ビットが設定されたディレクトリも受け入れてしまいます。bashおよびzshでは、
type -a fooのほうが短く書けますが、 移植性はありません。 -
Makefile。 レシピは
$(SHELL)を通して実行され、 デフォルトは/bin/shです。 プロジェクトがSHELLにPOSIX準拠ではないシェルを設定している場合は、command -vを使う前に、レシピをPOSIXシェルに固定してください。 たとえば、SHELL := /bin/shとします。
適用範囲
このルールは、POSIXシェルとして記述または実行されるすべてのものに適用されます。
Bashツールの呼び出し、
SKILL.md/README.md内のスニペット、
scripts/配下のスクリプト、
Makefile、
CI設定、
Dockerfile、
インストール手順、
推奨される1行コマンドが対象です。
対象外:
fish、
および内部でwhichをラップするツール
(CMakeのfind_program、npm binなど)。
ファイルの編集中にwhichの呼び出しを見つけた場合は、
同じ編集の一環として、同等のcommand -v形式に置き換えてください。