问题
$ 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+"$@"}
My interest lies in understanding who records the state change after calling cd. Is it in a file?
回答1:
This is not the cd builtin, and it doesn't actually work, except to tell if a directory can be changed into, by failing with a nonzero exit status if it cannot.
Try it:
"$(which cd)" /
...will do nothing.
The actual cd builtin is part of your shell, written in C, and calls the chdir() syscall. This syscall updates your process's state -- tracked by the kernel -- to have a different working directory.
...so, what is that chunk of shell script doing? Let's break it down:
builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}
...first, we're echoing the command itself (in a somewhat buggy fashion, due to the lack of quotes) into tr, and changing it to all lower-case, such that if it were being called via a hardlink named CD it would still map to the builtin named cd.
...second, ${1+"$@"} is passing all arguments ("$@") through, if there are any arguments (${foo+bar} expands to bar only if foo is defined).
Thus, we're calling the shell-builtin cd (which in turn calls the chdir() syscall), with arguments passed through. The reason this builtin has no effect other than determining success or failure is because it's running out-of-process from the executable that invoked it -- so it changes the working directory of the shell started by the #!/bin/sh shebang, but not of any process or shell above that in the tree.
So, what does a real cd builtin look like? Since it's short and easy-to-read, let's look at the Busybox ash implementation.
- Here is the entry-point...
- Here is the actual operation.
- Here is the manual for the syscall invoked by the actual operation.
来源:https://stackoverflow.com/questions/38776286/can-someone-explain-the-source-of-the-cd-shell-command