PWD
はカレントディレクトリが設定される変数ですが、POSIX ではただのシェル変数だけではなく環境変数としても標準化されています。そして実際のシェルでもおそらく環境変数になっているはずです。しかし一体なぜ PWD
は環境変数でなければならないのでしょうか?
PWD
変数はシェルで cd
コマンドを実行するたびに設定されます。またシェルの起動時にも設定されます。そのため原則として常にカレントディレクトリが設定されています。これは通常 pwd
コマンドの実行結果と同じです。PWD
変数を手動で unset
したり任意の値を代入すると pwd
コマンドの結果とは異なりますが、通常はそのような使い方をするべきではなく、それさえ守っていればシェルスクリプトから pwd
コマンドを実行してカレントディレクトリを取得するよりも PWD
変数を参照したほうが効率的(速い)です。
基本的にはシェルから参照するもので、環境変数として外部にエクスポートする必要がないように思えます。しかし POSIX では PWD
は環境変数として定義されています。
さっさと答えを書いてしまうと PWD
環境変数は「論理」カレントディレクトリを取得するために必要です。
カレントディレクトリを取得するには C 言語の getcwd
関数を実行します。しかし getcwd
関数で取得できるのは、「物理」カレントディレクトリです。例えば次のようなディレクトリ構造がある時
.
├── dir
└── link -> dir
link
ディレクトリにいるときに getcwd
関数を実行すると dir
ディレクトリにいることになります。なんでそうなっているのかと思うかもしれませんが、そういうものです。
通常はこの仕様でさほど困らないはずですが、link
ディレクトリにいるときに、新たなシェルを実行したらどうなるでしょうか? PWD
はシェルが実行されたときに初期化されますが、何も考えずに getcwd
関数でカレントディレクトリを取得すると dir
ディレクトリに変わってしまいます。
それじゃまずい(まずいの?)ということで、シェル起動時に PWD
環境変数があれば、そのパスをカレントディレクトリに設定します。ただし PWD
のパスが正しい場合、つまり PWD
環境変数で示す論理カレントディレクトリから導き出せる物理カレントディレクトリと、getcwd
関数から取得する物理カレントディレクトリが一致している場合に限ります。
この仕様については、人によってはなにか言いたいことがあるんじゃないかと思いますが、まあそういうものです。私としては別のシェルを起動したときに論理カレントディレクトリが物理カレントディレクトリに変わってしまうのは確かに嫌かなぁと思います。
なお Linux では getcwd
関数の代わりに(POSIX で標準化されていない)get_current_dir_name
関数を使うと、自分で PWD
環境変数が定義されていて物理カレントディレクトリと一致していればーなんて面倒なコードを書かずに同じことが実現できるようです。
PWD
がただのシェル変数ではなく環境変数であるのは、こういう理由からですという話でした。