我试图cd
接受从另一个命令重定向到的目录名称。这些方法都不起作用:
$ echo $HOME | cd
$ echo $HOME | xargs cd
这确实有效:
$ cd $(echo $HOME)
为什么第一组命令不起作用,是否还有其他命令也以这种方式失败?
答案1
cd
不是外部命令 - 它是 shell 内置函数。它在当前 shell 的上下文中运行,而不是像外部命令那样在 fork/exec'd 上下文中作为单独的进程运行。
您的第三个示例有效,因为 shell 在调用内置函数之前扩展了变量和命令替换cd
,以便cd
接收 的值${HOME}
作为其参数。
POSIX系统做有一个二进制文件cd
- 在我的 FreeBSD 机器上,它位于/usr/bin/cd
,但它并没有按照你的想法做。调用二进制文件cd
会导致 shell fork/exec 二进制文件,这确实会将其工作目录更改为您传递的名称。然而,一旦这样做,二进制文件就会退出,分叉/执行的进程就会消失,返回到 shell,它仍然位于启动之前所在的目录中。
答案2
cd
不读取标准输入。这就是为什么你的第一个例子不起作用。
xargs
需要一个命令名称,即独立可执行文件的名称。cd
需要是 shell 内置命令,如果它是可执行文件,则不会有任何效果(除了验证您是否可以更改到该目录以及它可能对可自动安装目录产生的潜在副作用之外)。这就是为什么你的第二个例子不起作用。
答案3
除了现有的好的答案之外,还值得一提的是,管道分叉了一个新进程,该进程有自己单独的工作目录。因此,尝试这样做是行不通的:
echo test | cd /
因此,在 shell 从该命令返回后,您将不会位于 / 文件夹中。
答案4
正如其他人所说,它不起作用,因为cd
它是 shell 内置命令,而不是外部程序,因此它没有任何可以通过管道传输任何内容的标准输入。
但是,即使它有效,它也不会执行您希望的操作:管道生成一个新进程并将第一个命令的标准输出重定向到第二个命令的标准输入,因此只有新进程才会更改其当前的工作目录;这不会以任何方式影响第一个过程。