実は which が見つけられないコマンドが存在します。シェル組み込みコマンド(built-in)と呼ばれる種類です。
この記事では、
type コマンドの使い方を解説します。コマンドがシェル組み込みなのか、外部バイナリなのか、エイリアスなのかを一発で判別できるようになります。シェルスクリプトのデバッグや、予期しない動作の原因調査にも役立ちます。この記事のポイント
・type コマンドでシェル組み込み・外部コマンド・alias を即座に判別できる
・which が何も返さない場合は type で確認するのが正しい手順
・type -a で同名コマンドの全候補をまとめて確認できる
・スクリプトのデバッグや意図しない動作の原因特定に実務で頻繁に使う
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ which だけでは不十分なのか
Linux のコマンドには大きく3種類あります。・シェル組み込みコマンド(built-in):bash 自身が処理する。ファイルとして存在しない
・外部コマンド:/usr/bin/ や /sbin/ 配下に実行ファイルが存在する
・エイリアス(alias):ユーザーが定義した別名。設定ファイルや対話シェルで定義される
which コマンドは「外部コマンドのファイルパスを探す」ツールです。シェル組み込みコマンドはファイルとして存在しないため、which では何も返ってきません。# which cd を実行しても何も返ってこない $ which cd $ # type なら正確に教えてくれる $ type cd cd is a shell builtin
cd がなぜ which で見つからないか不思議に思ったことがあるなら、まさにこの違いが理由です。type コマンドの基本的な使い方
1. コマンドの種類を確認する
type コマンドは bash の組み込みです。引数にコマンド名を指定するだけで動作します。# 書式 type コマンド名 # シェル組み込みコマンドの例 $ type cd cd is a shell builtin $ type echo echo is a shell builtin $ type pwd pwd is a shell builtin
2. 外部コマンドのパスを確認する
外部コマンドの場合は、実行ファイルのフルパスが表示されます。# 外部コマンドの確認 $ type ls ls is /usr/bin/ls $ type grep grep is /usr/bin/grep $ type python3 python3 is /usr/bin/python3 $ type nginx nginx is /usr/sbin/nginx
which コマンドと同じ情報です。ただし type は組み込みコマンドやエイリアスも含めて一元的に確認できます。3. エイリアスの確認
多くの環境ではll や la がエイリアスとして定義されています。type で確認するとエイリアスの中身まで表示されます。# エイリアスの確認 $ type ll ll is aliased to 'ls -l --color=auto' $ type la la is aliased to 'ls -A' # alias を自分で定義した場合 $ alias mygrep='grep --color=always' $ type mygrep mygrep is aliased to 'grep --color=always'
応用・実務での使い方
1. type -a で全候補を一覧表示する
同じ名前のコマンドが複数の場所に存在する場合があります(外部コマンドとシェル組み込みが両方ある、など)。type -a を使うとすべての候補を表示できます。# echo は組み込みと外部コマンドの両方が存在する $ type -a echo echo is a shell builtin echo is /usr/bin/echo # pwd も同様 $ type -a pwd pwd is a shell builtin pwd is /usr/bin/pwd # ls はエイリアス + 外部コマンドが両方ある場合 $ type -a ls ls is aliased to 'ls --color=auto' ls is /usr/bin/ls
-a オプションは、スクリプト内でどのコマンドが実際に呼ばれているのかを明確にしたい場合に役立ちます。シェルは上から順に優先します(エイリアス > 組み込み > 外部コマンド)。2. type -t でコマンドの種類を文字列で取得する
スクリプト内でコマンドの種類を条件分岐に使いたい場合はtype -t が便利です。alias・builtin・file・function のいずれかを返します。# type -t の出力例 $ type -t cd builtin $ type -t ls alias $ type -t grep file $ type -t myfunc function # スクリプト内での活用例 CMD="some_command" KIND=$(type -t "$CMD" 2>/dev/null) if [ "$KIND" = "file" ]; then echo "${CMD} は外部コマンドです" elif [ "$KIND" = "builtin" ]; then echo "${CMD} はシェル組み込みです" else echo "${CMD} が見つかりません" fi
3. シェル関数の確認
type はシェル関数も認識します。関数が定義されているかどうかをスクリプトから確認したい場合に使います。# シェル関数を定義する $ myfunc() { echo "hello from myfunc"; } # type で確認すると関数の中身が表示される $ type myfunc myfunc is a function myfunc () { echo "hello from myfunc" }
declare -f myfunc と同様の情報が得られます。4. コマンドが存在するかをチェックする
スクリプト内で外部コマンドのインストール確認をする場合、command -v と type のどちらかを使います。type -P は外部コマンドのパスのみを返し、組み込みは無視します。# type -P で外部コマンドのパスのみ返す(POSIX準拠環境では command -v が推奨) $ type -P nginx /usr/sbin/nginx $ type -P cd # 何も返さない(組み込みのため) # インストール確認スクリプトの例 if type -P git > /dev/null 2>&1; then echo "git はインストール済みです" else echo "git が見つかりません。インストールしてください" fi
トラブルシュート・よくある疑問
「command not found」なのに which では見つかる?
which はコマンドが PATH 上に存在するかを確認するだけで、実行できるかどうかは別問題です。実行ファイルのパーミッションが 0 や 600 になっていて実行できない場合でも、which ではパスが返ります。
# パーミッションが実行不可の場合 $ ls -l /usr/local/bin/myscript -rw-r--r-- 1 root root 512 Apr 24 10:00 /usr/local/bin/myscript $ which myscript /usr/local/bin/myscript # パスは返ってくる $ myscript bash: /usr/local/bin/myscript: Permission denied # でも実行できない # chmod で実行権を付ける $ sudo chmod 755 /usr/local/bin/myscript
alias が意図せず上書きしている場合の対処
rm が rm -i にエイリアスされていて、スクリプト内で確認なしに削除したいのに確認が出てしまう——これはよくあるトラブルです。# エイリアスを確認する $ type rm rm is aliased to 'rm -i' # スクリプト内でエイリアスを無視して外部コマンドを直接呼ぶ場合 # コマンド名の前にバックスラッシュを付ける \rm -rf /tmp/work_dir # または command コマンドを使う command rm -rf /tmp/work_dir
PATH の順序が影響するケース
同名のコマンドが複数の場所に存在する場合、シェルは PATH の左から順に探して最初に見つかったものを実行します。type -a で優先順位を把握しておくと、予期しない動作を防げます。# 現在の PATH を確認 $ echo $PATH /usr/local/bin:/usr/bin:/bin:/sbin # python3 がどこにあるか全候補確認 $ type -a python3 python3 is /usr/local/bin/python3 python3 is /usr/bin/python3 # /usr/local/bin が先にあるため、そちらが優先される
which との使い分けまとめ
| やりたいこと | コマンド | 組み込み対応 |
|---|---|---|
| コマンドの種類を確認する | type コマンド名 |
あり |
| 外部コマンドのパスを確認する | which コマンド名 または type -P コマンド名 |
なし(which)/ なし(type -P) |
| 同名コマンドの全候補を表示する | type -a コマンド名 |
あり |
| コマンド種別を文字列で取得する | type -t コマンド名 |
あり |
| コマンドが存在するか確認する(スクリプト向け) | command -v コマンド名 |
あり(POSIX準拠) |
本記事のまとめ
| 確認したいこと | コマンド |
|---|---|
| コマンドがシェル組み込みか外部コマンドかを調べる | type コマンド名 |
| エイリアスの定義内容を確認する | type コマンド名 |
| 同名コマンドの全候補と優先順位を確認する | type -a コマンド名 |
| コマンド種別を文字列で取得する(スクリプト内条件分岐) | type -t コマンド名 |
| 外部コマンドのパスのみを返す | type -P コマンド名 |
| シェル関数の定義内容を確認する | type 関数名 |
typeコマンドで一歩進んだ。次はLinux全体の仕組みを体系的に押さえませんか?
シェルの動作を理解することはLinux習熟の核心です。ネットの断片情報をつなぎ合わせるだけでは、現場でのトラブルに太刀打ちできません。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 前のページへ:sysctlコマンドでLinuxのカーネルパラメータを確認・変更する方法|永続化とセキュリティ設定も
- この記事の属するカテゴリ:Linuxtips・シェルスクリプトへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます