【Linux】which・type・commandの違い|コマンドの正体を調べる・aliasを見抜く

【Linux】which・type・commandの違い|コマンドの正体を調べる・aliasを見抜く Linux

「このpythonコマンドは、どこにインストールされたものが動いているんだろう?」「lsを打つと色が付くけど、これはaliasが効いているの?それとも本物?」——こうした「コマンドの正体」を調べるのがwhichtypecommandです。トラブルシューティングや環境確認で頻繁に使う、地味だけれど重要なコマンド群です。

この3つは似ているようで、調べられる範囲が違います。特に重要なのが、whichaliasやシェル関数を見抜けないという点です。「whichで調べたのに何も出てこない」というのは、実はコマンドがaliasや関数だったという場合がよくあります。この記事では、実機のLinux(WSLのDebian)で3つの違いを実際に比較しながら、正しい調べ方を整理します。

先に結論

  • which コマンド実行ファイルのパスを表示します(PATH上を探す)。
  • whichはalias・シェル関数・組み込みコマンドを見抜けません(空を返すことも)。
  • type コマンドは、alias・関数・組み込み・実体ファイルをすべて区別できます。
  • type -tで種別だけ(file/alias/function/builtin)を取得できます。
  • command -vはPOSIX標準で、スクリプトで移植性高くコマンドの存在確認に使えます。
  • 「正体をちゃんと知りたいならtype」が基本です。

コマンドが見つかる仕組み(PATH)は環境変数とPATH、aliasの仕組みはalias、シェルの設定は同記事もあわせて参考になります。

スポンサーリンク

whichの基本:実行ファイルのパスを調べる

whichは、指定したコマンドがどの実行ファイルとしてPATH上に存在するかを調べ、そのパスを表示します。「このコマンドの実体はどこ?」を知る基本の方法です。

which の基本
# コマンドの実行ファイルのパスを表示
which ls
# /usr/bin/ls

which python3
# /usr/bin/python3

# -a: PATH上の複数の該当を全部表示
which -a ls
# /usr/bin/ls
# /bin/ls

実機でも、which ls/usr/bin/lsという実体のパスが表示され、which -a lsPATH上に複数ある同名コマンドをすべて/usr/bin/ls/bin/ls)表示できることを確認しました。whichPATHを順に探して「最初に見つかった実行ファイル」を返すため、「実際に動くのはどのバージョンか」を確認するのに便利です。ただし、これから見るようにwhichには大きな死角があります。

【最重要】whichはaliasや関数を見抜けない

whichの重大な制約がこれです。whichは「PATH上の実行ファイル」しか探さないため、aliasやシェル関数として定義されたコマンドを調べても、何も表示されない(正体を教えてくれない)のです。

aliasに対するwhichの死角(実証)
# ll を alias として定義
alias ll='ls -la'

# which で調べても…何も出てこない!
which ll
#           ← 空(aliasは実行ファイルではないので見つけられない)

# type なら正体が分かる
type ll
# ll is aliased to `ls -la'   ← alias だと教えてくれる
whichはaliasを見抜けない・typeを使う(実証)

実機で、llls -laのaliasとして定義した状態でwhich llを実行すると、何も表示されませんでした(空)whichPATH上の実行ファイルだけを探すコマンドなので、aliasやシェル関数の存在を知らないのです。一方、type llll is aliased to 'ls -la'と、aliasであることと中身まで正しく教えてくれました。同様に、シェル関数をwhichで調べても空になりますが、typeなら関数名 is a functionと関数の定義まで表示されます。whichで調べたのに何も出ない」ときは、そのコマンドがalias・関数・組み込みコマンドのいずれかである可能性が高いのです。コマンドの正体を正確に知りたいなら、whichではなくtypeを使うのが正解です。

typeの基本:正体をすべて区別する

typebashに組み込まれたコマンドで、指定した名前がalias・シェル関数・組み込みコマンド(builtin)・実体ファイルのどれなのかを、すべて区別して教えてくれます。

type で正体を区別
# 実行ファイル
type ls
# ls is /usr/bin/ls

# 組み込みコマンド(cdやechoはbash自身の機能)
type cd
# cd is a shell builtin

type echo
# echo is a shell builtin

# 関数
type myfunc
# myfunc is a function
# myfunc () { ... }   ← 関数の中身も表示される

実機でも、type ls実行ファイルのパスtype cdtype echoshell builtin(組み込みコマンド)type myfuncfunction(関数の定義も表示)と、それぞれ正しく区別できました。cdecho実行ファイルではなくbash自身の機能(builtin)だと分かるのもtypeならではです。コマンドの正体を1つのコマンドで完全に把握できるのがtypeの強みです。

type -tで種別だけを取得する

スクリプトの中で「このコマンドはaliasか、実体か」を判定したいときは、type -tが便利です。filealiasfunctionbuiltinという種別の単語だけを返します。

type -t で種別だけ
type -t ls
# file       ← 実行ファイル

type -t cd
# builtin    ← 組み込み

type -t ll
# alias      ← alias

type -t myfunc
# function   ← 関数

# スクリプトでの判定に使える
if [ "$(type -t mycommand)" = "function" ]; then
  echo "関数として定義されています"
fi

実機でも、type -tlsfilecdbuiltinllaliasmyfuncfunctionと、種別を表す単語だけを返すことを確認しました。この短い出力はシェルスクリプトでの条件分岐に最適で、「このコマンドが関数なら〜、実体なら〜」といった処理を書けます。

command -v:移植性の高い存在確認

command -vは、POSIX標準で定められた方法で、コマンドの存在確認や場所の特定ができます。どのシェルでも同じように動くため、移植性が重要なスクリプトではwhichよりcommand -vが推奨されます。

command -v
# 実行ファイルならパスを表示
command -v ls
# /usr/bin/ls

# alias なら alias 定義を表示
command -v ll
# alias ll='ls -la'

# スクリプトでの定番: コマンドが存在するか確認する
if command -v git > /dev/null 2>&1; then
  echo "git はインストールされています"
else
  echo "git が見つかりません"
fi
スクリプトの存在確認はcommand -vが定番(実証)

実機で、command -v ls実行ファイルのパスを、command -v llalias定義を返すことを確認しました。whichは環境によってはインストールされていないこともあり、シェルによって挙動も微妙に異なりますが、command -vはbash・sh・zshなどで共通して使えるため、スクリプトの互換性が高まります。とくに「あるコマンドがインストールされているかを確認してから処理を分岐する」という定番パターンでは、if command -v git > /dev/null 2>&1; then ...という書き方がよく使われます(出力を/dev/nullに捨てて、成否だけを見る形です)。whichを使ったインストール確認をスクリプトで見かけたら、command -vに置き換えるとより堅牢になります。

主な違い一覧

3つのコマンドの守備範囲をまとめます。

コマンド 特徴
which 実行ファイルのパスのみ。alias/関数は見抜けない
which -a PATH上の該当をすべて表示
type alias/関数/組み込み/実体をすべて区別
type -t 種別だけ(file/alias/function/builtin)
command -v POSIX標準・移植性が高い存在確認

よくある失敗

whichで調べたのに何も表示されない

そのコマンドがalias・関数・組み込みの可能性があります。typeで調べます。

スクリプトでwhichを使って存在確認する

whichは環境依存です。移植性の高いcommand -vを使います。

cdやechoをwhichで探して見つからない

これらは組み込みコマンド(builtin)です。typeで確認できます。

実際に動くコマンドと違うバージョンを見ている

which -aでPATH上の全該当を確認し、優先順位を調べます。

aliasの中身を確認せず本来の動作と混同する

typeでalias定義を確認し、必要なら本来のコマンドを実行します。

よくある質問

Qwhichとtypeの違いは何ですか?
AwhichはPATH上の実行ファイルのパスだけを調べます。一方typeは、alias・シェル関数・組み込みコマンド・実体ファイルのどれなのかをすべて区別できます。実機でも、aliasをwhichで調べると何も表示されないのに対し、typeならaliasであることと中身まで分かることを確認しています。正体を正確に知りたいならtypeです。
Qwhichで調べても何も出てこないのはなぜですか?
Aそのコマンドが実行ファイルではなく、alias・シェル関数・組み込みコマンドのいずれかである可能性が高いです。whichはPATH上の実行ファイルしか探さないため、これらを見つけられません。type コマンド名で調べると、正体が分かります。
Qcdやlsの色付けはaliasなのか確認したいです。
Atype lsを実行してください。ls is aliased to ...と表示されればalias、ls is /usr/bin/lsと表示されれば実体のコマンドです。多くの環境ではlsが色付けオプション付きのaliasになっています。cdtype cdで「shell builtin(組み込み)」と分かります。
Qスクリプトでコマンドの存在を確認するには?
Acommand -v コマンド名 > /dev/null 2>&1を使い、その成否(終了コード)で分岐するのが定番です。command -vはPOSIX標準で移植性が高く、bash・sh・zshなどで共通して動きます。whichは環境によっては入っていないこともあるため、スクリプトではcommand -vが推奨されます。
Qコマンドの種別だけを取得したいです。
Atype -t コマンド名を使います。file(実行ファイル)・aliasfunctionbuiltinのいずれかの単語だけが返るため、スクリプトの条件分岐に便利です。実機でも、それぞれのコマンドで正しい種別が返ることを確認しています。

まとめ

  • which実行ファイルのパスのみ。alias・関数は見抜けません
  • typeは、alias・関数・組み込み・実体をすべて区別できます。
  • type -tで種別だけ(file/alias/function/builtin)を取得できます。
  • スクリプトの存在確認は、移植性の高いcommand -vが定番です。
  • 「正体を正確に知りたいならtype」を基本に覚えておきましょう。

whichtypecommandは、「このコマンドは何者か」を突き止めるための道具です。whichにはaliasや関数を見抜けない死角があることさえ知っておけば、環境調査やトラブルシューティングでつまずくことはなくなります。PATHaliasの記事とあわせて、コマンドが「どこから来て、何として動くのか」を理解しておきましょう。