ご想像のとおり、正確な動作はシェルに依存していますが、機能のベースラインレベルはPOSIXによって指定されています。
標準のシェルコマンド言語(ほとんどのシェルはそのスーパーセットを実装しています)のコマンド検索と実行には多くのケースがありますが、ここでPATH
は、が使用されている場合のみに関心があります。その場合:
XBD環境変数で説明されているように、PATH環境変数を使用してコマンドが検索されます。
そして
検索が成功した場合:
[...]
シェルは、別のユーティリティ環境でユーティリティを実行execl()
し、パス引数を検索の結果得られたパス名に設定して関数[...] を呼び出すのと同等のアクションを実行します。
失敗した場合、実行は失敗し、終了コード127がエラーメッセージとともに返されます。
この動作はexecvp
、特に関数と一致しています。すべてのexec*
関数は、実行するプログラムのファイル名、一連の引数(argv
プログラムのもの)、および環境変数のセットを受け入れます。PATH
ルックアップを使用するバージョンの場合、POSIXは次のように定義します。
引数ファイルは、新しいプロセスイメージファイルを識別するパス名を作成するために使用されます[...]このファイルのパスプレフィックスは、環境変数PATHとして渡されたディレクトリの検索によって取得されます
PATHの動作は、他の場所で次のように定義されています。
この変数は、特定の関数とユーティリティがファイル名だけでわかる実行可能ファイルを検索する際に適用する一連のパスプレフィックスを表すものとします。接頭辞は、<コロン>( ':')で区切られます。ゼロ以外の長さのプレフィックスがこのファイル名に適用されるとき、プレフィックスがで終わっていない場合、プレフィックスとファイル名の間に<slash>が挿入されます。長さゼロのプレフィックスは、現在の作業ディレクトリを示すレガシー機能です。これは、2つの隣接する文字( "::")、リストの残りの前にある最初の<コロン>、またはリストの残りに続く末尾の<コロン>として表示されます。厳密に準拠するアプリケーションは、実際のパス名(。など)を使用して、PATHの現在の作業ディレクトリを表します。リストは最初から最後まで検索され、指定された名前と適切な実行権限を持つ実行可能ファイルが見つかるまで、各プレフィックスにファイル名が適用されます。探しているパス名に<スラッシュ>が含まれている場合、パス接頭辞による検索は実行されません。パス名が<スラッシュ>で始まる場合、指定されたパスは解決されます(パス名の解決を参照)。PATHが設定されていないかnullに設定されている場合、パス検索は実装定義です。
それは少し密度が高いので、要約:
- プログラム名に
/
(スラッシュ、U + 002F SOLIDUS)が含まれている場合は、通常の方法でパスとして扱い、このプロセスの残りをスキップします。シェルの場合、このケースは技術的には発生しません(シェルルールですでに対処されているため)。
- の値は
PATH
各コロンで断片に分割され、各コンポーネントは左から右に処理されます。特別な(歴史的な)ケースとして、空でない変数の空のコンポーネントは.
(現在のディレクトリ)として扱われます。
- 各コンポーネントについて、プログラム名が最後に追加され、結合が行わ
/
れ、その名前のファイルの存在が確認されます。存在する場合は、有効な実行(+ x)権限も確認されます。これらのチェックのいずれかが失敗した場合、プロセスは次のコンポーネントに進みます。それ以外の場合、コマンドはこのパスに解決され、検索が実行されます。
- コンポーネントが不足すると、検索は失敗します。
- に何もない
PATH
、または存在しない場合は、好きなようにしてください。
実際のシェルには、このルックアップの前に見つかる組み込みコマンドがあり、多くの場合、エイリアスと関数も含まれます。それらはと相互作用しませんPATH
。POSIXはそれらの周りのいくつかの動作を定義し、あなたのシェルにはもっと多くの動作があるかもしれません。
これのexec*
大部分を実行することに依存することは可能ですが、実際にはシェルは、特にキャッシュの目的でこのルックアップ自体を実装する場合がありますが、空のキャッシュの動作は同様です。シェルはここではかなり広い緯度を持ち、コーナーケースでは微妙に異なる動作をします。
ご覧のとおり、Bash はハッシュテーブルを使用して、以前に表示されたコマンドの完全なパスを記憶していhash
ます。このテーブルには関数を使用してアクセスできます。コマンドを初めて実行すると検索され、結果が見つかるとテーブルに追加されるので、次に試すときにわざわざ探す必要はありません。
一方、zshでは、PATH
通常、シェルの起動時にフルが検索されます。ルックアップテーブルには、検出されたすべてのコマンド名があらかじめ入力されているため、通常、ランタイムルックアップは必要ありません(新しいコマンドが追加されない限り)。これまでに存在しなかったコマンドをタブ補完しようとすると、このことに気付くでしょう。
などの非常に軽量なシェルは、dash
できるだけ多くの動作をシステムライブラリに委任する傾向があり、過去のコマンドパスを覚えておく必要はありません。
PATH
の間bash
とzsh
、私は私の混乱を解決するのに役立ちます!