which / type / command
| 対応: | which | 全Linux |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) | ||
| type / command | 全Linux | |
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
コマンドの場所や種類を調べるコマンドです。which、type、command -v はどれも「このコマンドはどこにあるか/何者か」を調べるために使われますが、動作と用途が異なります。特にシェルスクリプトで移植性が求められる場合は使い分けが重要です。
構文
which は指定したコマンドの実行ファイルのパスを表示します。PATH 環境変数を検索します。
which コマンド名
type はコマンドの種類(組み込みコマンド・エイリアス・関数・外部コマンド)を表示します。bash/zsh の組み込みコマンドです。
type コマンド名 type -a コマンド名
command -v は POSIX 準拠のコマンド存在確認です。シェルスクリプトで移植性が必要な場面に適しています。
command -v コマンド名
コマンド比較
| コマンド | 対象 | エイリアスを表示 | 組み込みを表示 | POSIX準拠 |
|---|---|---|---|---|
| which | 外部コマンド(PATH検索) | 環境依存 | 表示しない | 非準拠 |
| type | すべての種類 | 表示する | 表示する | 非準拠(bash/zsh組み込み) |
| command -v | すべての種類 | 表示する | 表示する | 準拠 |
サンプルコード
which で実行ファイルのフルパスを確認します。実行ファイルのフルパスを確認する例です。
which bash /bin/bash
実行するコマンドは次の通りです。
which python3 /usr/bin/python3
コマンドが見つからない場合は何も表示されないか、エラーメッセージが出力されます。
which myapp which: no myapp in (/usr/local/bin:/usr/bin:/bin) echo $? 1
type でコマンドの種類を調べます。組み込みコマンド・エイリアス・外部コマンドを区別できます。
type cd cd is a shell builtin type ls ls is aliased to `ls --color=auto' type bash bash is /bin/bash type grep grep is /usr/bin/grep
-a オプションを付けると同名のコマンドをすべて列挙します。エイリアスと外部コマンドが両方ある場合に便利です。
type -a ls ls is aliased to `ls --color=auto' ls is /usr/bin/ls ls is /bin/ls
command -v でコマンドの存在確認をします。POSIX 準拠なので #!/bin/sh で始まる移植性重視のスクリプトでも使えます。
command -v git /usr/bin/git command -v nonexistent
コマンドが存在しない場合は何も出力されず、終了ステータスが 1 になります。
check_dependencies.sh
#!/bin/sh
# アプリ起動前の依存コマンドチェックスクリプト
# 必要なコマンドの存在確認
for cmd in curl jq git; do
if ! command -v "$cmd" > /dev/null 2>&1; then
echo "エラー: '$cmd' が見つかりません。インストールしてください。" >&2
exit 1
fi
done
echo "全コマンド確認完了。アプリを起動します。"
APP_LOG="$HOME/app_startup.log"
echo "$(date): アプリ起動" >> "$APP_LOG"
コマンドが存在するかどうかで処理を分岐する例です。python3 があれば使い、なければ python にフォールバックします。
python_check.sh
#!/bin/sh
# Python コマンドを判定してデータを処理する
if command -v python3 > /dev/null 2>&1; then
PYTHON=python3
elif command -v python > /dev/null 2>&1; then
PYTHON=python
else
echo "Python が見つかりません。" >&2
exit 1
fi
$PYTHON process_data.py
概要
which は外部の実行ファイルのパスを探すツールです。シェルの組み込みコマンドやエイリアスについては何も返さないことがあります。which ls は /bin/ls のパスを返しますが、ls がエイリアスに設定されていても which はそのエイリアスを表示しないことがあります(シェルや環境による)。
type は bash や zsh の組み込みコマンドで、エイリアス・関数・組み込み・外部コマンドのすべてを識別できます。POSIX で定義されていないため #!/bin/sh スクリプトでは使えない場合があります。
command -v は POSIX で定義されており、もっとも移植性の高い方法です。コマンドが存在すればパスかコマンド名を出力し、なければ終了ステータス 1 を返します。シェルスクリプト内でコマンドの存在確認には command -v を使うことが広く推奨されています。
よくあるミス
よくあるミス1: which がエイリアスを表示しない
which は PATH 上の外部コマンドしか探しません。エイリアスや関数は表示されないため、「which で確認したパスのコマンドを実行したが、実際に動くのはエイリアス」というズレが起きることがあります。
alias ls='ls --color=auto' which ls /bin/ls type ls ls is aliased to `ls --color=auto'
which ls はエイリアスを無視して /bin/ls を返しています。実際に端末で ls を打つと ls --color=auto が動きます。コマンドの実際の動作を確認したい場合は type が使えます。
よくあるミス2: which の終了ステータスを信用しすぎる
環境によっては which が存在しないコマンドに対しても終了ステータス 0 を返すことがあります。スクリプト内でコマンドの存在確認をするために which を使うと、環境によって動作が変わる可能性があります。
以下は which を使った存在確認の例です。環境によって終了ステータスの扱いが異なるため動作が安定しません。
#!/bin/sh
if which check_inventory.sh > /dev/null 2>&1; then
echo "コマンドが見つかりました"
fi
POSIX 準拠の command -v を使った例です。どの POSIX 互換シェルでも同じ終了ステータスを返します。
#!/bin/sh
if command -v check_inventory.sh > /dev/null 2>&1; then
echo "コマンドが見つかりました"
fi
シェルスクリプトでコマンドの存在確認をする場合、command -v を使うと環境に依存しない判定ができます。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。