为什么 popd 上的 shell 扩展不从堆栈中删除目录?

为什么 popd 上的 shell 扩展不从堆栈中删除目录?

当我popd单独使用时,它会从堆栈中删除一个目录并将我带到该目录。但是,如果我这样做,cd $(popd)则不会从堆栈中删除任何目录。

既然进程只是分叉,并且结果被放置在 shell 扩展的位置,为什么不从堆栈中取出目录呢?

答案1

语法$(...)不是“shell 扩展”,而是“命令替换”。

使用此语法,将创建一个子 shell,执行其中的命令并在命令行上返回标准输出。所以,举例来说,

x=$(cd /tmp ; ls)

将在子 shell 中运行该cd命令,这意味着主进程的当前目录保持不变。

以类似的方式,cd $(popd)将导致popd在子进程中运行,因此仅影响子进程;父进程未受影响。

通过这个简单的测试,您可以看到它已经影响了子进程:

$ pushd /tmp
/tmp ~
$ pushd /
/ /tmp ~
$ dirs
/ /tmp ~
$ cd $(popd ; dirs >&2)
/tmp ~
$ dirs
/tmp /tmp ~

表明在 shelldirs >&2内部$(...)目录堆栈已被弹出,但是因为这是一个孩子进程的父堆栈未受影响。

答案2

命令替换$(…)在子 shell 中运行命令。子 shell 最初是主 shell 的相同副本,但从那时起,主 shell 和子 shell 就过着自己的生活。

  1. shell 进程创建管道和叉子。
  2. 子进程运行popd时其输出连接到管道,然后退出。
  3. 父级从管道读取数据并将其替换到命令行中。

由于popd在子进程中运行,因此其作用仅限于子进程。目录从堆栈中取出 — 从子堆栈中取出。父级中的堆栈没有任何变化。

1几乎相同;这些差异在这里无关紧要。

答案3

pushd并将popd堆栈保留在名为 的变量中DIRSTACK,该变量在子 shell 中发生变化,但在父 shell 中保持不变,就像任何其他环境变量一样。

进一步阅读

相关内容