popdのシェル拡張がスタックからディレクトリを削除しないのはなぜですか?

popdのシェル拡張がスタックからディレクトリを削除しないのはなぜですか?

単独で使用すると、スタックからpopdディレクトリを削除してそのディレクトリに移動します。ただし、これによりスタックからcd $(popd)ディレクトリが削除されなくなります。

プロセスがフォークされ、結果がシェル拡張位置に配置されるので、スタックからディレクトリを削除するのはどうでしょうか?

答え1

構文は$(...)「シェル拡張」ではなく「コマンドの置換」です。

この構文を使用すると、サブシェルが生成され、その中のコマンドが実行され、標準出力がコマンドラインに返されます。例えば、

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シェル内の$(...)ディレクトリスタックがポップされたことを示します。子供プロセスの親スタックは影響を受けません。

答え2

コマンド置換は$(…)サブシェルでコマンドを実行します。サブシェルはメインシェルの同じコピーから始まりますが、その時点からメインシェルとサブシェルはそれぞれの人生を生きていきます。

  1. シェルプロセスはパイプとフォークを生成します。
  2. 子プロセスは、popdその出力がパイプに接続されている間に実行され、終了します。
  3. 親はパイプからデータを読み取り、それをコマンドラインに置き換えます。

子プロセスで実行されるため、popdその効果は子プロセスに制限されます。目次はいスタックから削除 - サブスタックから削除します。親スタックに変更はありません。

1はほぼ同じです。これらの違いはここでは関係ありません。

答え3

pushd他の環境変数と同様に、子シェルでは変更されますが、親シェルでは変更されていないままの変数popdにスタックを保持します。DIRSTACK

追加読書

関連情報