Overview
The cd (change directory) command is one of the most fundamental and frequently used commands in Linux and Unix systems. It's a shell builtin command that changes the current working directory of the shell process. Unlike most commands that execute as separate processes, cd must be a shell builtin because it needs to modify the shell's own environment.
Understanding cd and its various shortcuts and patterns is essential for efficient navigation of the Linux filesystem. The command supports both absolute paths (starting from root /) and relative paths (starting from the current directory), as well as several special shortcuts that can significantly speed up your workflow.
Key Characteristics
| Property | Description |
|---|---|
| Type | Shell builtin (bash, zsh, sh, ksh, etc.) |
| Purpose | Change the current working directory |
| Common Use | Navigate filesystem, access files and directories |
| Path Types | Absolute paths, relative paths, special shortcuts |
cd were an external command, it would execute in a child process. When that child process changed its directory and exited, the parent shell would remain in its original directory. As a builtin, cd executes within the shell's own process, actually changing the shell's working directory.
Special Directory Shortcuts
| Shortcut | Meaning | Example |
|---|---|---|
~ |
Home directory of current user | cd ~ or just cd |
. |
Current directory | cd . (rarely used alone) |
.. |
Parent directory | cd .. |
- |
Previous directory (toggles between two locations) | cd - |
/ |
Root directory | cd / |
~username |
Home directory of specified user | cd ~john |
Detailed Examples
Example 1: Basic Directory Navigation
/home/craig
$ cd /var/log
$ pwd
/var/log
$ cd /etc/systemd
$ pwd
/etc/systemd
$ cd system
$ pwd
/etc/systemd/system
cd /var/log uses an absolute path (starts with /) to jump directly to /var/log from anywhere. Then cd /etc/systemd jumps to another absolute location. Finally, cd system uses a relative path - since we're in /etc/systemd, it appends "system" to our current location, taking us to /etc/systemd/system. The pwd (print working directory) command confirms our location after each change.
Example 2: Going Home Multiple Ways
/var/log/apache2
# Method 1: Just cd with no arguments
$ cd
$ pwd
/home/craig
# Method 2: Explicit home directory
$ cd /var/log
$ cd ~
$ pwd
/home/craig
# Method 3: Using $HOME variable
$ cd /tmp
$ cd $HOME
$ pwd
/home/craig
# Navigate to subdirectory of home
$ cd ~/Documents
$ pwd
/home/craig/Documents
cd with no arguments is the quickest method. You can also explicitly use the tilde (~) which the shell expands to your home directory path. The $HOME environment variable also contains your home directory path. The tilde can also be used as a prefix to navigate to subdirectories of home (like ~/Documents), which is very convenient and saves typing the full path.
echo ~
Example 3: Navigating Up the Directory Tree
/home/craig/projects/web/frontend/src/components
# Go up one level
$ cd ..
$ pwd
/home/craig/projects/web/frontend/src
# Go up multiple levels at once
$ cd ../..
$ pwd
/home/craig/projects/web/frontend
# Go up three levels
$ cd ../../..
$ pwd
/home/craig/projects
# Combine with other navigation
$ cd ../docs
$ pwd
/home/craig/docs
..) represents the parent directory. You can chain multiple .. together with slashes to move up multiple levels in a single command. For example, ../.. goes up two levels, ../../.. goes up three levels, and so on. You can also combine upward navigation with moving to a different branch: cd ../docs goes up one level, then into the docs directory at that level.
../ instead of doing multiple separate cd .. commands.
Example 4: Using cd - to Toggle Between Directories
/home/craig/Documents
$ cd /var/log
$ pwd
/var/log
# Toggle back to previous directory
$ cd -
/home/craig/Documents
$ pwd
/home/craig/Documents
# Toggle back again
$ cd -
/var/log
$ pwd
/var/log
# This is stored in $OLDPWD
$ echo $OLDPWD
/home/craig/Documents
cd - command is incredibly useful for switching between two locations. It takes you to the previous directory and also prints the new path. The shell maintains this in the $OLDPWD environment variable. This is perfect for situations where you're working between two directories - like editing code in your project directory and checking logs in /var/log. You can quickly toggle back and forth without retyping paths.
Example 5: Accessing Other Users' Home Directories
/home/craig
# View another user's home (if permissions allow)
$ cd ~apache
$ pwd
/var/www
$ cd ~nobody
$ pwd
/nonexistent
# Back to your home
$ cd ~craig
$ pwd
/home/craig
# Or simply
$ cd
$ pwd
/home/craig
# View what a username expands to
$ echo ~root
/root
$ echo ~bin
/bin
~username) to navigate to that user's home directory. This is useful for system administration tasks or when working on shared systems. Note that some system users (like apache or nobody) may have home directories in non-standard locations, and some may have home directories that don't actually exist. You need appropriate permissions to actually enter and read other users' home directories.
cd to another user's home directory doesn't mean you can read or modify files there. Normal users typically don't have permissions to enter other users' home directories unless explicitly granted.
Example 6: Handling Spaces and Special Characters in Paths
/home/craig
# Create directory with spaces for demonstration
$ mkdir "My Documents"
$ mkdir "Project Files"
# Wrong - treats each word as separate argument
$ cd My Documents
bash: cd: My: No such file or directory
# Correct Method 1: Use quotes
$ cd "My Documents"
$ pwd
/home/craig/My Documents
# Correct Method 2: Escape spaces with backslash
$ cd ..
$ cd My\ Documents
$ pwd
/home/craig/My Documents
# Tab completion automatically escapes spaces
$ cd ..
$ cd Pro[TAB]
$ cd Project\ Files/
$ pwd
/home/craig/Project Files
my_documents or my-documents. This makes command-line work much easier.
Example 7: Using CDPATH for Quick Navigation
$ export CDPATH="/home/craig:/var/log:/etc"
# Now you can cd to subdirectories of CDPATH entries from anywhere
$ pwd
/tmp
$ cd Documents
$ pwd
/home/craig/Documents
$ cd apache2
/var/log/apache2
$ pwd
/var/log/apache2
$ cd systemd
/etc/systemd
$ pwd
/etc/systemd
# Add to ~/.bashrc to make permanent
$ echo 'export CDPATH=".:~:/var/log:/etc"' >> ~/.bashrc
# The leading . means current directory is checked first
$ cd /tmp
$ mkdir systemd
$ cd systemd
$ pwd
/tmp/systemd # Current directory found first
CDPATH is a powerful shell variable that specifies a list of directories to search when you use cd with a relative path. When you type cd dirname, the shell first checks if "dirname" exists in the current directory. If not, it searches each directory listed in CDPATH. This is incredibly useful if you frequently work in certain directory trees - you can jump directly to common locations without typing full paths. Note that it's conventional to include . (current directory) as the first entry in CDPATH so that local directories are found first.
cd output. For scripts, you may want to unset CDPATH or explicitly use absolute paths.
Example 8: Using cd with Command Substitution
$ cd $(find /usr -name "include" -type d -print -quit 2>/dev/null)
$ pwd
/usr/include
# cd to the directory containing a specific file
$ cd $(dirname $(which httpd))
$ pwd
/usr/sbin
# cd to the parent of a found file
$ cd $(dirname $(find /etc -name "httpd.conf" -print -quit 2>/dev/null))
$ pwd
/etc/httpd
# Go to directory from a symlink target
$ cd $(dirname $(readlink -f /usr/bin/python))
$ pwd
/usr/bin
# cd to directory of the most recently modified file
$ cd $(dirname $(ls -t /var/log/*.log | head -1))
$ pwd
/var/log
$(command) or backticks) allows you to use the output of one command as an argument to cd. This is powerful for dynamic directory changes based on searches or system state. The examples show finding directories with find, navigating to the directory of an executable using which and dirname, and following symbolic links with readlink. This technique is especially useful in scripts or when you don't know the exact path but know how to find it.
cd. If the substitution fails or returns unexpected results, you might end up in an unintended directory. The 2>/dev/null suppresses error messages from find, which is useful for cleaner output.
Example 9: cd Options and Error Handling
# Enable cdspell to auto-correct minor typos
$ shopt -s cdspell
$ cd /ect
/etc
$ pwd
/etc
# Try with a worse typo - won't auto-correct if too different
$ cd /usr/lbi
bash: cd: /usr/lbi: No such file or directory
# cd with -P follows physical directory structure (resolves symlinks)
$ cd /var/run
$ pwd
/var/run
$ pwd -P
/run # /var/run is actually a symlink to /run
$ cd -P /var/run
$ pwd
/run # -P resolved the symlink
# cd with -L uses logical directory structure (default)
$ ln -s /usr/local/lib mylib
$ cd -L mylib
$ pwd
/home/craig/mylib
$ pwd -P
/usr/local/lib
# Check if cd succeeded before continuing
$ cd /some/directory && echo "Success! Now in $(pwd)" || echo "Failed to change directory"
cd behavior. The cdspell option (enabled with shopt -s cdspell) automatically corrects minor typos in directory names. The -P flag makes cd resolve symbolic links and show the physical path, while -L (default) maintains the logical path including symlinks. The last example shows error handling: using && (and) and || (or) operators, you can execute commands conditionally based on whether cd succeeded. This is crucial in scripts where you want to ensure you're in the correct directory before performing operations.
cd succeeded in scripts: cd /target/dir || exit 1. This prevents dangerous operations from running in the wrong directory if the cd fails.
Example 10: Advanced cd Techniques and Directory Stack
$ pwd
/home/craig
# pushd changes directory AND saves current location
$ pushd /var/log
/var/log ~
$ pwd
/var/log
# Stack another directory
$ pushd /etc
/etc /var/log ~
# View the stack
$ dirs -v
0 /etc
1 /var/log
2 ~
# Jump to a specific stack position
$ pushd +1
/var/log /etc ~
$ pwd
/var/log
# popd removes top and returns to previous
$ popd
/etc ~
$ pwd
/etc
$ popd
~
$ pwd
/home/craig
# Create a cd function with history in ~/.bashrc
$ cat >> ~/.bashrc << 'EOF'
cd() {
builtin cd "$@" && ls -la
}
EOF
# Now cd also runs ls after changing
$ source ~/.bashrc
$ cd /tmp
total 48
drwxrwxrwt 10 root root 4096 Nov 24 08:30 .
drwxr-xr-x 19 root root 4096 Oct 15 14:22 ..
...
pushd and popd commands. Unlike cd - which only remembers one previous directory, the directory stack can hold many directories. pushd changes to a directory while saving your current location; popd returns to the previous location and removes it from the stack. The dirs command shows the stack contents. You can even override the cd command in your ~/.bashrc to add custom behavior, like automatically listing directory contents after each change. This shows how flexible shell builtins can be customized to match your workflow.
cd function to their ~/.bashrc that automatically performs actions like running ls, git status, or activating Python virtual environments when entering directories.
Common Options
| Option | Description | Example |
|---|---|---|
-L |
Follow symbolic links (default behavior) | cd -L /var/mail |
-P |
Use physical directory structure (resolve symlinks) | cd -P /var/run |
-@ |
Browse file attributes (if supported by filesystem) | cd -@ somefile |
-@ option is rarely used and only works on systems with extended attribute support. Most users will only ever use -L and -P.
Environment Variables Related to cd
| Variable | Purpose | Example |
|---|---|---|
HOME |
User's home directory path | echo $HOME → /home/craig |
PWD |
Current working directory | echo $PWD → /var/log |
OLDPWD |
Previous working directory | echo $OLDPWD → /home/craig |
CDPATH |
Search path for cd command | export CDPATH=".:~:/var/log" |
Related Commands
Best Practices and Tips
Always use tab completion when typing paths. It's faster, prevents typos, automatically escapes special characters, and confirms the path exists.
cd→ Go home (fastest way)cd -→ Toggle between two directoriescd ..→ Go up one levelcd ../..→ Go up two levelscd ~/path→ Access home subdirectories from anywhere
If you frequently work in certain directory trees, add them to CDPATH in your ~/.bashrc:
In scripts, always use absolute paths or explicitly check if cd succeeded:
- Not checking if
cdsucceeded in scripts before performing operations - Forgetting to quote or escape paths with spaces or special characters
- Using
cdin the middle of a pipeline (won't affect subsequent commands) - Assuming relative paths work the same in scripts as in interactive shells
Exit Status
| Code | Meaning |
|---|---|
| 0 | Success - directory changed |
| 1 | Failure - directory doesn't exist, no permissions, or invalid path |