popd
を単独で使用すると、スタックからディレクトリが削除され、そのディレクトリに移動します。ただし、cd $(popd)
を実行すると、スタックからディレクトリが削除されません。
プロセスは単純にフォークされ、結果はシェル拡張の代わりに配置されるので、なぜディレクトリがスタックから削除されないのですか?
コマンド置換$(…)
は、サブシェルでコマンドを実行します。サブシェルはメインシェルの同一¹コピーとして始まりますが、その時点からメインシェルとサブシェルは独自の生活を送っています。
popd
を実行し、終了します。popd
は子プロセスで実行されるため、その効果は子プロセスに限定されます。ディレクトリisスタックから削除されました—子のスタックから削除されました。親のスタックには何も起こりません。
¹ ほぼ同じ。ここでは違いは関係ありません。
構文$(...)
は「シェル拡張」ではなく、「コマンド置換」です。
この構文を使用すると、サブシェルが作成され、内部のコマンドが実行され、標準出力がコマンド行に返されます。だから、例えば、
_x=$(cd /tmp ; ls)
_
サブシェルでcd
コマンドを実行します。これは、メインプロセスの現在のディレクトリが変更されないままであることを意味します。
同様に、cd $(popd)
はpopd
を子プロセスで実行するため、子プロセスにのみ影響します。親プロセスは変更されていません。
この簡単なテストで、子プロセスに影響を与えていることがわかります。
_$ pushd /tmp
/tmp ~
$ pushd /
/ /tmp ~
$ dirs
/ /tmp ~
$ cd $(popd ; dirs >&2)
/tmp ~
$ dirs
/tmp /tmp ~
_
_dirs >&2
_は、$(...)
シェル内でディレクトリスタックがポップされたことを示していますが、これはchildプロセスであるため、親スタックは変更されていません。
pushd
とpopd
は、スタックをDIRSTACK
という変数に保持します。この変数はサブシェルで変更されますが、他の環境変数と同様に、親シェルでは変更されません。
さらに読む 。