cd Command

Change Directory - Navigate the Filesystem

cd [OPTION] [DIRECTORY]

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
Why cd is a Builtin: If 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

$ pwd
/home/craig
$ cd /var/log
$ pwd
/var/log
$ cd /etc/systemd
$ pwd
/etc/systemd
$ cd system
$ pwd
/etc/systemd/system
Explanation: This demonstrates both absolute and relative path navigation. 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.
Tip: Use absolute paths when you know exactly where you want to go, regardless of current location. Use relative paths for nearby directories to save typing.

Example 2: Going Home Multiple Ways

$ pwd
/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
Explanation: There are multiple ways to return to your home directory. Simply typing 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.
Note: The tilde expansion happens in the shell before the command executes. You can see what it expands to with: echo ~

Example 3: Navigating Up the Directory Tree

$ pwd
/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
Explanation: The double-dot (..) 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.
Productivity Tip: When you're deep in a directory tree and need to go up several levels, count the levels and use the appropriate number of ../ instead of doing multiple separate cd .. commands.

Example 4: Using cd - to Toggle Between Directories

$ pwd
/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
Explanation: The 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.
Real-World Usage: This is extremely handy when you're compiling code in one directory and testing the binary in another, or when you're editing configuration files in /etc and checking their effects in /var/log.

Example 5: Accessing Other Users' Home Directories

$ pwd
/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
Explanation: You can use the tilde followed by a username (~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.
Permissions: Just because you can 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

$ pwd
/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
Explanation: Directory names with spaces require special handling. Without quotes or escaping, the shell interprets each space-separated word as a separate argument. You can either enclose the entire path in quotes (single or double) or escape each space with a backslash. The most practical approach is to use tab completion, which automatically escapes spaces and other special characters for you.
Best Practice: When creating directories, avoid spaces in names if possible. Use underscores or hyphens instead: my_documents or my-documents. This makes command-line work much easier.

Example 7: Using CDPATH for Quick Navigation

# Set up CDPATH environment variable
$ 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
Explanation: 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.
CDPATH Gotcha: When CDPATH successfully finds a directory, it prints the full path. This behavior can be surprising and may interfere with scripts that parse cd output. For scripts, you may want to unset CDPATH or explicitly use absolute paths.

Example 8: Using cd with Command Substitution

# Find and cd to a directory
$ 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
Explanation: Command substitution (using $(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.
Caution: Always test command substitutions before using them with 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

# bash options that affect cd behavior

# 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"
Explanation: Bash offers several options that modify 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.
Scripting Best Practice: Always check if 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

# Using the directory stack (pushd, popd, dirs)
$ 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 ..
...
Explanation: For more sophisticated directory navigation, bash provides the directory stack via 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.
Power User Tip: Many users add a custom 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
Note: The -@ 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

1. Use Tab Completion Religiously

Always use tab completion when typing paths. It's faster, prevents typos, automatically escapes special characters, and confirms the path exists.

2. Learn the Quick Shortcuts
  • cd → Go home (fastest way)
  • cd - → Toggle between two directories
  • cd .. → Go up one level
  • cd ../.. → Go up two levels
  • cd ~/path → Access home subdirectories from anywhere
3. Set Up CDPATH for Your Workflow

If you frequently work in certain directory trees, add them to CDPATH in your ~/.bashrc:

export CDPATH=".:~:~/projects:/var/log:/etc"
4. Use Absolute Paths in Scripts

In scripts, always use absolute paths or explicitly check if cd succeeded:

cd /var/log || { echo "Failed to cd to /var/log"; exit 1; }
Common Mistakes to Avoid:
  • Not checking if cd succeeded in scripts before performing operations
  • Forgetting to quote or escape paths with spaces or special characters
  • Using cd in 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