We're all familiar with using the cd command to jump around directories. Normally you need to know and type either an absolute path or a relative directory name when using cd, except for common shortcuts like:
> cd
/Users/kai
> cd ./code
/Users/kai/code
> cd ..
/Users/kai
> cd -
/Users/kai/code
In the above examples, we jumped $HOME (aka ~) by providing no arguments, then into an adjacent directory, into the parent directory, and back into the last directory, respectively. What I've seen most people do in practice is either manually type most of the path/directory, and then rely on tab completion to cycle through and finish, or they create aliases to use a single command as a shortcut to jump to their favorite directory:
> alias c="cd ~/code"
> c
/Users/kai/code
These all work, but if you're like me, you have a hundred directories worth of projects that you navigate in and out of.
CDPATH
CDPATH works similar to PATH in that you provide a comma-delimited list of directories that become the search path for the cd command. Let's look at a practical example to understand the benefits. For this example, assume I keep my projects organized in /Users/kai/code:
~/code
โฏ tree
.
โโโ alpha
โโโ beta
โโโ charlie
โโโ delta
โโโ echo
โโโ foxtrot
โโโ golf
โโโ hotel
9 directories, 0 files
I can use CDPATH to set ~/code as a search path for cd:
export CDPATH=~/code
With this set, I can now type cd golf, from anywhere, and cd will utilize the search path to look for matching subdirectory names in each of the top-level directories that I provided to CDPATH.
Gotcha
In almost all cases, you will want the first directory in your CDPATH to be the current directory (aka .) so that you can continue to cd into relative directories:
export CDPATH=.:~/code
Now, if I have a subdirectory named golf in my current working directory, I will cd into the relative path, ./golf, rather than /Users/kai/code/golf. But what if I preferred to go to the latter? The next section has the answer.
Zoxide (Recommended)
Now that you have intuition into how search paths work, I trust that you can fix PATH issues yourself. Also, you don't actually need to use CDPATH directly because there is a more productive solution.
Zoxide provides the same jumpability benefit as CDPATH and adds quality of life improvements such as completions, duplicate directory name resolution, and automatic directory tracking so that you don't ever need to manage any environment variables yourself.
Install zoxide and its dependency fzf, then add the initialization script to your shell config and reload your shell:
> brew install zoxide fzf
...
๐บ /opt/homebrew/Cellar/zoxide/0.9.8: 18 files, 1MB
...
๐บ /opt/homebrew/Cellar/fzf/0.65.1: 19 files, 4.5MB
...
> echo 'eval "$(zoxide init zsh)"' >> ~/.zshrc
> exec zsh
Now, from this point forward, use z instead of cd. Zoxide will remember where to jump around to, so that you can recall later even faster. Example:
> z golf
zoxide: no match found
> z ~/code/golf
/Users/kai/code/golf
> z
/Users/kai
> z golf
/Users/kai/code/golf
Since installing Zoxide, I haven't jumped to ~/code/golf before, so using z golf found no matches. After I z into the directory myself, Zoxide knows where I've been, enabling me to jump back from anywhere via z golf, or even with a partial word match like z go. Eventually using something really short like z go can become ambiguous once you visit any other directories that start with or contain go. When path matches become similar, Space+Tab to resolve.
Here's a short animated demo, that I lifted directly from the official Zoxide GitHub repo.
Relevant Music
Only one song makes sense here. ๐