Navigation (cd, pwd)
Navigating the filesystem efficiently is the foundation of every shell skill. cd, pwd, pushd/popd, history shortcuts, and modern replacements like z turn directory-hopping from tedium into reflex.
cd, pushd/popd, fzf, z, aliases
EXAMPLE
# 1) Basics
pwd # /home/mara/projects/app
cd /etc/nginx # absolute path
cd nginx.conf # NOPE — cd needs a directory; this errors
cd ~ # home
cd ~mara # mara's home
cd # also home
cd .. # parent
cd ../sibling # parent's sibling
cd - # PREVIOUS directory (toggle)
# 2) Show what's there
ls # current dir
ls -la # long + hidden (dotfiles)
ls -lh # human-readable sizes
ls -lt # newest first
ls -1 # one entry per line (scripts)
tree -L 2 # 2-level tree (install: brew/apt install tree)
# 3) Globbing — shell expands paths before commands see them
ls *.md # all top-level .md files
ls **/*.test.ts # globstar — requires shopt -s globstar (bash)
ls assets/*.{png,jpg,webp} # brace expansion (alternatives)
ls ./.{git,vscode,idea}/ # hidden dirs by name
# 4) Show + go in one move
ls ~/projects/app/src # see what's there
cd !$ # !$ = last word of previous command — re-uses path
# Result: cd ~/projects/app/src
# 5) Directory stack — pushd / popd / dirs
pushd ~/projects/app # cd there + push old onto stack
pushd /etc/nginx # cd there + push again
dirs -v # see the stack
# 0 /etc/nginx
# 1 ~/projects/app
# 2 ~/projects/old-dir
popd # pop top, cd back
cd ~+2 # cd to stack item index 2 (bash)
# 6) History shortcuts
!! # repeat last command
sudo !! # repeat with sudo prefix
!?nginx # last command containing 'nginx'
!42 # history command number 42
^old^new # rerun last command replacing 'old' with 'new'
!$ # last argument of previous command
!^ # FIRST argument of previous command
!* # all args of previous command
# 7) Reverse search
Ctrl+R cd /etc # incrementally search history (very useful)
Ctrl+R Ctrl+R # cycle through matches
# Modern alternatives: atuin (great history), mcfly (ML-ranked), or fzf integration:
# ~/.bashrc: bind -x '"\C-r": __fzf_history__' (after sourcing fzf shell completions)
# 8) Modern replacements
z projects/app # 'zoxide' (or 'z') — jumps based on history of cd-d places
z nginx # cd ~/work/something/nginx (fuzzy match)
fd 'name' src/ # find replacement; respects .gitignore
eza -la --git # modern ls with git status
bat path/file # cat with syntax highlight + paging
fzf # fuzzy-find files; integrate with cd: alias cdf='cd $(fd -t d | fzf)'
# 9) Useful aliases (~/.bashrc or ~/.zshrc)
alias ll='ls -la'
alias la='ls -A'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias home='cd ~'
alias work='cd ~/work'
alias src='cd $(git rev-parse --show-toplevel)/src'
# 10) Symbolic links — readlink + cd -P
cd /usr/local/bin/python # follows symlink
pwd # logical path (symlink path)
pwd -P # PHYSICAL path (resolved)
readlink -f /usr/local/bin/python # canonical resolved path
# Disable symlink-following globally:
set -P # pwd shows physical paths
# 11) Bash CDPATH — auto-search common dirs
export CDPATH=".:$HOME:$HOME/projects:/srv"
cd app # finds ~/projects/app even though you're not there
# Use sparingly — confuses scripts.
# 12) Going home and exploring quickly
take projects/new-thing # mkdir -p + cd into it (zsh function; copy to bash)
mkcd() { mkdir -p "$1" && cd "$1"; }
# 13) Useful prompts (PS1)
export PS1='\\[\\e[34m\\]\\w\\[\\e[0m\\] $ ' # show full path
# Or use starship / oh-my-posh for richer prompts with git status.
# 14) Going to a sibling project — find + cd
cd "$(find ~/work -type d -name '*api*' -maxdepth 3 | fzf)"
# 15) Common bugs
# • cd into a file by accident → 'not a directory'; use ls then cd
# • cd - keeps toggling between two dirs forever; use pushd/popd for a stack
# • Hidden assumption: scripts run with PWD = where they're invoked from, not where the script lives
# Use 'cd "$(dirname "${BASH_SOURCE[0]}")"' at the top of scripts to anchor
# • CDPATH side effects on scripts — leave it off in non-interactive shells
# • Aliases not loading in scripts — alias only works in interactive shells; use functions
# • Spaces in paths — quote: cd "$HOME/My Documents"
# • Symlinks confusing relative paths — pwd -P for physical, pwd for logical
Why it matters
Pair cd -, pushd/popd, and Ctrl+R for stock-shell efficiency, then upgrade to zoxide, fzf, fd, and eza for jump-anywhere navigation. Always anchor scripts with cd "$(dirname "${BASH_SOURCE[0]}")" so they don’t depend on the caller’s working directory.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
pwd # print current directory cd /var/log cd ~ && cd - # home and previousTry it Yourself »
Exercise
Print current directory.
Three letters.
Discussion
Loading…