This week’s Read the Manual entry is late because yesterday I wrote up my thoughts on programming language pedagogy instead. Today’s subject is the trusty cd
command. How much can there be to changing directories? Not a lot, but there are still some interesting things to learn here!
There are, gloriously, zero flags for the command… if, like me, you use fish. It takes a single argument: cd [DIRECTORY]
. The main interesting thing is that fish “ships a wrapper function around the builtin cd” which lets you use cd -
to go to the previous directory.
(As an aside: I often don’t even bother with typing cd
, because in fish, you don’t have to. You just type a valid directory name and fish moves the current directory there. This is one of those things that I have still not fully internalized, though, even 5 years along!)
So about that built-in — finding the man page is a bit of an adventure in digging. If you man cd
in any built-in shell on macOS, e.g. zsh, you will get the man page for BUILTIN(1)
and an instruction to “See the built-in command description in the appropriate shell manual page.” The obvious next move is man zsh
or man bash
and searching for cd
. That doesn’t help in the case of zsh
, because its docs are (reasonably!) broken up into other man pages; you actually need to do man zshbuiltins
. It does work from man bash
, though.
In bash, there are two options: -P
to use the “physical” directory structure and not to follow symlinks, -L
to force symlinks to be followed. It also gets configuration from the CDPATH
variable, which changes how cd
“searches” for non-absolute paths.
In zsh, there are two additional options, -q
for quiet, which skips calling functions zsh lets you use for printing output when you change directories, and -s
for refusing to navigate if the path includes symlinks. There are also two additional forms you can call in zsh:
-
You can pass two values, like
cd <old> <new>
, to replace<old>
with<new>
in the current directory name, e.g. if I were in~/dev/chriskrycho/some-nested-path
and typedcd chriskrycho rust-lang
, it would try to go to~/dev/rust-lang/some-nested-path
. Cool? 🤷🏻♂️ -
You can pass
+n
or-n
wheren
is a number and move through your directory history byn
entries. I actually missed this a bit in fish early on, but fish gives thecdh
command and I actually find that more useful, because remembering exact directory history is hard!
And that’s pretty much it. zsh also supports some other shenanigans using shell variables, but since I am a fish user, I… really don’t care. 😅
By far the most useful thing I learned today was how to read the manual entries for built-ins. The most useful thing I learned from the man page itself is that if you just do cd
, with no argument at all, it goes to HOME
. Instead of typing cd ~
, you can just skip the extra characters and the extra dance with the Shift key. Neat!