Files and directories · bash builtin
cd
Change the shell's current working directory.
cd [-L|-P] [DIRECTORY]
cd changes the directory the shell is "in", which is where relative paths are resolved from.
It has to be a shell builtin: a separate program could only change its own directory, not the
shell's. For the same reason, a cd inside a script, a subshell ( ... ) or a pipeline does not
move the shell you typed the command in.
With no argument, cd goes to $HOME. cd - goes back to the previous directory (stored in
$OLDPWD) and prints it. Bash also keeps $PWD up to date, which is what the prompt and
pwd show.
Symbolic links make "where am I" ambiguous. By default (-L, logical) bash remembers the path
you typed, links included, so cd .. goes back the way you came. cd -P resolves links and
lands in the real directory. To jump around and come back later, pushd and popd keep a
stack of directories.
Examples
Move into a directory
cd data
pwd
/home/dev/demo/data
The relative path data is resolved from the current directory, /home/dev/demo, and the
shell now works from /home/dev/demo/data.
Go up one level
cd src/lib
cd ..
pwd
/home/dev/demo/src
.. is the parent directory. cd ../.. goes up two levels.
Go to your home directory
cd
pwd
cd ~/demo/logs
pwd
/home/dev /home/dev/demo/logs
cd with no argument goes to $HOME. The shell expands ~ to the same directory, so
~/demo/logs is an absolute path that works from anywhere.
Jump back to the previous directory
cd /tmp
cd ~/demo/src
cd -
cd -
/tmp /home/dev/demo/src
cd - switches to $OLDPWD, the directory you were in before the last cd, and prints it.
Repeating it toggles between two directories.
Changing into a directory that does not exist
cd nosuchdir
echo "exit status: $?"
/bin/bash: line 1: cd: nosuchdir: No such file or directory exit status: 1
cd prints an error and returns 1, and the shell stays where it was. In scripts write
cd "$dir" || exit 1, so a failed cd cannot make the following commands run in the
wrong directory.
Trying to cd into a file
cd notes.txt
/bin/bash: line 1: cd: notes.txt: Not a directory
Only directories can be entered; a regular file gives "Not a directory" and status 1.
Directories with spaces in the name
Setup run before this example
mkdir "old reports"cd old reports
cd "old reports" && pwd
/bin/bash: line 1: cd: too many arguments /home/dev/demo/old reports
Unquoted, the shell splits old reports into two arguments and bash's cd refuses with
"too many arguments". Quoting (or escaping the space as old\ reports) passes one argument.
Logical versus physical path through a symlink
Setup run before this example
ln -s src/lib lib-linkcd lib-link && pwd
cd -P . && pwd
/home/dev/demo/lib-link /home/dev/demo/src/lib
After cd lib-link, bash reports the path the way you reached it. cd -P . resolves the
link and moves to the real location, /home/dev/demo/src/lib.
cd in a subshell does not affect the shell
(cd logs && ls)
pwd
app.log app.log.1 error.log /home/dev/demo
The parentheses run a subshell; it changes directory, lists logs, and exits. The outer
shell never moved, which makes this a tidy way to run one command elsewhere.
Shortcut directories with CDPATH
CDPATH=.:~/demo/src
cd ~
cd lib
/home/dev/demo/src/lib
When the name is not found relative to the current directory, cd tries each directory in
CDPATH. It found lib under ~/demo/src and printed the full path to show where it went.
Keep . first in CDPATH, or a local directory with the same name gets shadowed.
Common pitfalls
cdin a script changes the script's directory, not your shell's. To change your shell's directory,sourcethe script or define a function.Always check
cdin scripts:cd "$dir" || exit. A failedcdfollowed byrm -rf *deletes the wrong files.Exporting
CDPATHmakes every script'scduse it and print paths; set it in your interactive~/.bashrcwithoutexport.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
cdis part of the shell, not GNU or BSD userland; bash, dash and zsh all support-L,-Pandcd -. zsh adds extras such ascd old new(substitute in the current path).
Options worth knowing
A selection, described in our own words. For the full list, see bash(1).
| Option | What it does |
|---|---|
-L | Follow symlinks logically: keep the path as typed (default). |
-P | Resolve symlinks and use the physical directory. |
-e | With -P, return failure if the resulting directory cannot be determined. |
Related
pwdPrint the full path of the current working directory.pushdChange to a directory and remember the previous one on a stack, so popd can return to it.popdRemove the top directory from the directory stack and change back to the next one.lsList the contents of directories, or the details of individual files.- Subshells and command groupingThe difference between ( ... ) and { ...; }, what a subshell inherits and what it cannot change, which constructs create one, and what that costs.
- QuotingSingle quotes, double quotes, backslashes and $'...', what each protects, and the unquoted-variable bugs they prevent, each shown failing and then fixed.