有人可以解释 `cd` shell 命令的来源吗?

Can someone explain the source of the `cd` shell command?

$ cat $(which cd)
#!/bin/sh
# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19   cperciva Exp $
# This file is in the public domain.
builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}

我的兴趣在于了解谁记录了调用cd后的状态变化。它在文件中吗?

这是 不是 cd 内置函数,它实际上不起作用,除了判断一个目录是否 可以 被更改为,如果不能,则以非零退出状态失败。

试一试:

"$(which cd)" /

...什么都不做。


实际的 cd 内置函数是 shell 的一部分,用 C 语言编写,并调用 chdir() 系统调用。此系统调用更新您的进程状态(由内核跟踪)以具有不同的工作目录。


...那么, 那段 shell 脚本在做什么?让我们分解一下:

builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}

...首先,我们echo将命令本身(由于缺少引号,以一种有点错误的方式)转换为 tr,并将其更改为所有低-情况下,如果它是通过名为 CD 的硬链接调用的,它仍将映射到名为 cd.

的内置函数

...其次,${1+"$@"} 正在传递所有参数 ("$@"),if 有任何参数 (${foo+bar} 展开仅当定义了 foo 时才为 bar

因此,我们调用 shell-builtin cd(它又调用 chdir() 系统调用),并传递参数。这个内置函数除了确定成功或失败之外没有其他影响的原因是因为它在调用它的可执行文件中处于 运行 进程外——因此它更改了由 shell 启动的工作目录#!/bin/sh shebang,但不是任何进程或树中的 shell 以上进程。


那么,real cd 内置函数是什么样的?由于它简短易读,让我们看一下 Busybox ash 实现。

  • Here 是入口点...
  • Here是实际操作。
  • Here为实际操作调用的syscall的手册