環境変数 PATH に空文字があるとカレントディレクトリが指定されているのと同じ意味になる
何だと!?
タイトルのまんま。
恥ずかしながらこれ今まで知らなかった。
もしかして常識だったりする?
ちなみに確認したのは Linux だけど、glibc の posix サブディレクトリ配下の execl*
execvpe
の挙動なので glibc 使ってればみんな一緒じゃないかな?知らんけど…
PATH
が設定されていない時
環境変数 unset PATH
とした状態。
この場合、PATH=/bin:/usr/bin
と設定されているのと同じ意味になる(追記も参照のこと)。
当然カレントディレクトリは含まれていない。
PATH
が空の時
環境変数 PATH=
とした状態。
「PATH
環境変数が設定されていない時」とは異なる事に注意。
この場合、PATH=.
と設定されているのと同じ意味になる。
つまり、カレントディレクトリが含まれている。
PATH
の最後が :
で終わっている場合
環境変数 例えば、PATH=/bin:/usr/bin:
となっている状態。
この場合、PATH=/bin:/usr/bin:.
と設定されているのと同じ意味になる。
つまり、PATH
の最後にカレントディレクトリが含まれている。
PATH
の先頭が :
から始まっている場合
環境変数 例えば、PATH=:/bin:/usr/bin
となっている状態。
この場合、PATH=.:/bin:/usr/bin
と設定されているのと同じ意味になる。
つまり、PATH
の最初にカレントディレクトリが含まれている。
PATH
の途中に ::
が含まれる場合
環境変数 例えば、PATH=/bin::/usr/bin
となっている状態。
この場合、PATH=/bin:.:/usr/bin
と設定されているのと同じ意味になる。
つまり、PATH
の途中にカレントディレクトリが含まれている。
これって結構怖くね?
基本的にはカレントディレクトリを PATH
に追加することは無いんだが、間違って :
で始まったり :
で終わったりは結構やりそう(今までもやってそう)な気がする…
2021/9/26追記
PATH
が設定されていない時に PATH=/bin:/usr/bin
と同じ意味になるのはあくまでも exec[vl]p*
の挙動で、シェルから実行した場合の挙動はシェルの種類によるようだ。(shela_ さん、ko1nksm さんコメントありがとうございます)
ちなみに、env -u PATH コマンド
とやると execvp
を使ってるっぽいので上記の記載通り PATH=/bin:/usr/bin
と同等になる。
よくよく考えれば、シェルは外部コマンドを実行する際にはコマンドのフルパスをキャッシュするので、PATH
を自力で解決しているはずなので、exec[vl]p*
の挙動と同じになるとは限らないな。
そう考えると、空文字の場合の挙動もシェルによって違っていておかしくない気はするが、どうもそこは統一されているようだ。
Discussion
環境変数
PATH
が未定義もしくは空文字の場合の挙動は、おそらくシェル依存の話だと思ったので確認してみました。確認したシェルは dash、bash、ksh、mksh、yash、posh、zsh、busybox ash でいずれも Debian 10 の標準パッケージに含まれているものです。unset PATH
のとき/bin:/usr/bin
ではなくカレントディレクトリを参照します/bin:/usr/bin
もカレントディレクトリも参照しません/bin:/usr/bin
を参照しているようです(その他のディレクトリを参照するかどうかは未確認です)
PATH=""
のとき/bin:/usr/bin
もカレントディレクトリも参照しませんシェルで
PATH
を未定義または空文字にしてからシェルスクリプトを実行した場合=シェルスクリプトの中で起動時にPATH
が未定義または空文字であった場合にPATH
が初期化されます。Debian 環境では以下のように初期化されましたがおそらくシステムによって違うのではないかと思っています。PATH
が未定義(unset PATH
)の場合/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.
/usr/bin:/bin
/bin:/usr/bin
/bin:/usr/bin:/usr/ucb:/usr/local/bin
/sbin:/usr/sbin:/bin:/usr/bin
PATH
が空文字(export PATH=""
)の場合/usr/local/bin:/usr/bin:/bin:/usr/games
1984 年にベル研から出ている The UNIX Programming Environment という本にも記述があります.
さらに,この本では全体に渡ってカレントディレクトリが
PATH
に含まれている環境を想定しているようです. こんな問題も出ていました.