2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なぜPWDはただのシェル変数ではなく環境変数なのか?

Last updated at Posted at 2025-07-14

PWD はカレントディレクトリが設定される変数ですが、POSIX ではただのシェル変数だけではなく環境変数としても標準化されています。そして実際のシェルでもおそらく環境変数になっているはずです。しかし一体なぜ PWD は環境変数でなければならないのでしょうか?

PWD 変数はシェルで cd コマンドを実行するたびに設定されます。またシェルの起動時にも設定されます。そのため原則として常にカレントディレクトリが設定されています。これは通常 pwd コマンドの実行結果と同じです。PWD 変数を手動で unset したり任意の値を代入すると pwd コマンドの結果とは異なりますが、通常はそのような使い方をするべきではなく、それさえ守っていればシェルスクリプトから pwd コマンドを実行してカレントディレクトリを取得するよりも PWD 変数を参照したほうが効率的(速い)です。

基本的にはシェルから参照するもので、環境変数として外部にエクスポートする必要がないように思えます。しかし POSIX では PWD は環境変数として定義されています。

さっさと答えを書いてしまうと PWD 環境変数は「論理」カレントディレクトリを取得するために必要です。

カレントディレクトリを取得するには C 言語の getcwd 関数を実行します。しかし getcwd 関数で取得できるのは、「物理」カレントディレクトリです。例えば次のようなディレクトリ構造がある時

link は dir ディレクトリへのシンボリックリンク
.
├── dir
└── link -> dir

link ディレクトリにいるときに getcwd 関数を実行すると dir ディレクトリにいることになります。なんでそうなっているのかと思うかもしれませんが、そういうものです。

通常はこの仕様でさほど困らないはずですが、link ディレクトリにいるときに、新たなシェルを実行したらどうなるでしょうか? PWD はシェルが実行されたときに初期化されますが、何も考えずに getcwd 関数でカレントディレクトリを取得すると dir ディレクトリに変わってしまいます。

それじゃまずい(まずいの?)ということで、シェル起動時に PWD 環境変数があれば、そのパスをカレントディレクトリに設定します。ただし PWD のパスが正しい場合、つまり PWD 環境変数で示す論理カレントディレクトリから導き出せる物理カレントディレクトリと、getcwd 関数から取得する物理カレントディレクトリが一致している場合に限ります。

この仕様については、人によってはなにか言いたいことがあるんじゃないかと思いますが、まあそういうものです。私としては別のシェルを起動したときに論理カレントディレクトリが物理カレントディレクトリに変わってしまうのは確かに嫌かなぁと思います。

なお Linux では getcwd 関数の代わりに(POSIX で標準化されていない)get_current_dir_name 関数を使うと、自分で PWD 環境変数が定義されていて物理カレントディレクトリと一致していればーなんて面倒なコードを書かずに同じことが実現できるようです。

PWD がただのシェル変数ではなく環境変数であるのは、こういう理由からですという話でした。

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?