Bash Cheatsheet
Essential Bash shell commands, keyboard shortcuts, variables, conditionals, loops, functions, pipes, and redirection. Applies to bash 4+ and zsh.
Navigation
| Command | Description |
|---|---|
pwd | Print current directory |
cd <dir> | Change directory |
cd ~ | Go to home directory |
cd - | Go to previous directory |
ls | List directory contents |
ls -la | List all files including hidden, long format |
pushd <dir> | Push directory onto stack and cd to it |
popd | Pop directory from stack and return to it |
File Operations
| Command | Description |
|---|---|
cp src dst | Copy file |
cp -r src dst | Copy directory recursively |
mv src dst | Move or rename file/directory |
rm <file> | Delete file |
rm -rf <dir> | Delete directory and contents (use with care) |
mkdir <dir> | Create directory |
mkdir -p a/b/c | Create nested directories |
touch <file> | Create empty file or update timestamp |
ln -s target link | Create symbolic link |
find . -name "*.log" | Find files matching pattern |
chmod 755 <file> | Set file permissions |
chown user:group <file> | Change file owner and group |
Viewing Files
| Command | Description |
|---|---|
cat <file> | Print file contents |
less <file> | Paginated viewer (q to quit, / to search) |
head -n 20 <file> | Show first 20 lines |
tail -n 20 <file> | Show last 20 lines |
tail -f <file> | Follow file as it grows (useful for logs) |
grep "pattern" <file> | Search file for pattern |
grep -r "pattern" . | Recursive search in current directory |
wc -l <file> | Count lines in file |
sort <file> | Sort lines alphabetically |
uniq | Remove duplicate adjacent lines (use after sort) |
Redirection & Pipes
| Syntax | Description |
|---|---|
cmd > file | Redirect stdout to file (overwrite) |
cmd >> file | Redirect stdout to file (append) |
cmd < file | Feed file as stdin to cmd |
cmd1 | cmd2 | Pipe stdout of cmd1 to stdin of cmd2 |
cmd 2> err.log | Redirect stderr to file |
cmd &> file | Redirect both stdout and stderr to file |
cmd 2>/dev/null | Suppress stderr |
cmd1 && cmd2 | Run cmd2 only if cmd1 succeeds |
cmd1 || cmd2 | Run cmd2 only if cmd1 fails |
cmd1 ; cmd2 | Run both regardless of exit codes |
Variables
| Syntax | Description |
|---|---|
VAR=value | Assign (no spaces around =) |
$VAR or ${VAR} | Expand variable |
${VAR:-default} | Use default if VAR is unset or empty |
${VAR:?error} | Exit with error if VAR is unset |
readonly VAR=value | Make variable read-only |
export VAR | Make variable available to child processes |
unset VAR | Remove variable |
${#VAR} | Length of variable value |
$0, $1, $2… | Script name, positional args |
$@ | All arguments as separate words |
$# | Number of arguments |
$? | Exit code of last command |
$$ | PID of current shell |
Conditionals
# if / elif / else
if [[ "$VAR" == "hello" ]]; then
echo "greeting"
elif [[ "$VAR" == "bye" ]]; then
echo "farewell"
else
echo "other"
fi
# File tests
if [[ -f "$FILE" ]]; then echo "is a file"; fi
if [[ -d "$DIR" ]]; then echo "is a directory"; fi
if [[ -z "$STR" ]]; then echo "empty string"; fi
if [[ -n "$STR" ]]; then echo "non-empty string"; fi
if [[ -e "$PATH" ]]; then echo "exists"; fi | Test Flag | Meaning |
|---|---|
-f | Is a regular file |
-d | Is a directory |
-e | Exists (file or dir) |
-z | String is empty |
-n | String is non-empty |
-r / -w / -x | File is readable / writable / executable |
-eq / -ne / -lt / -gt | Numeric: equal / not equal / less / greater |
Loops
# for loop over values
for item in a b c; do
echo "$item"
done
# for loop over files
for f in *.txt; do
echo "$f"
done
# C-style for loop
for ((i=0; i<5; i++)); do
echo "$i"
done
# while loop
while [[ $count -lt 10 ]]; do
((count++))
done
# until loop
until [[ $count -ge 10 ]]; do
((count++))
done Functions
# Define
greet() {
local name="$1" # local variable
echo "Hello, $name!"
return 0 # exit code
}
# Call
greet "World"
result=$(greet "World") # capture output Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl+C | Interrupt (kill) current process |
Ctrl+Z | Suspend current process (resume with fg) |
Ctrl+D | Send EOF / exit shell |
Ctrl+L | Clear screen |
Ctrl+R | Search command history (reverse search) |
!! | Re-run last command (e.g. sudo !!) |
Ctrl+A | Move cursor to start of line |
Ctrl+E | Move cursor to end of line |
Ctrl+W | Delete word to the left |
Tab | Autocomplete command or path |
Process Management
| Command | Description |
|---|---|
ps aux | List all running processes |
kill <pid> | Send SIGTERM to process |
kill -9 <pid> | Force kill (SIGKILL) |
pkill <name> | Kill processes by name |
jobs | List background jobs |
bg %1 | Resume job 1 in background |
fg %1 | Bring job 1 to foreground |
nohup cmd & | Run cmd immune to hangups, in background |
Frequently Asked Questions
How do I check if a file exists in bash?
Use the -f flag inside a conditional: if [[ -f "/path/to/file" ]]; then echo "exists"; fi. To check for a directory, use -d. To check that a path exists regardless of type, use -e. Always quote the path in case it contains spaces: [[ -f "$MYPATH" ]].
What is the difference between single and double quotes in bash?
Double quotes ("...") allow variable expansion and command substitution inside them — $VAR and $(cmd) are expanded. Single quotes ('...') treat everything literally — no expansion at all. Use double quotes when you need variable values in a string. Use single quotes when you want the exact literal string, such as regex patterns or awk scripts that contain $.
How do I loop over files in bash?
Use a glob in a for loop: for f in *.txt; do echo "$f"; done. Always quote "$f" to handle filenames with spaces. To loop recursively over all files, you can use find . -name "*.txt" -exec echo \; or enable globstar with shopt -s globstar and then use for f in **/*.txt; do ....