Bash Cheat Sheet
Quick reference for Bash: variables, redirection, pipes, conditionals, loops, and one-liners.
Bash is a command interpreter built around composing small programs with expansion, pipelines, and exit statuses. Quote data by default, inspect failures explicitly, and prefer readable scripts over clever one-liners.
Variables and quoting
Assignments have no spaces around =. Parameter expansion reads a value, while double quotes preserve it as one argument and prevent word splitting and pathname expansion.
name="Ada Lovelace"
printf 'Hello, %s\n' "$name"
count=${#name}
readonly VERSION="1.0"
| Form | Meaning |
|---|---|
VAR=value | Set a shell variable for the current shell. |
export VAR | Pass the variable to child processes. |
${VAR:-default} | Use default when VAR is unset or empty. |
${VAR:?message} | Stop with message when VAR is unset or empty. |
"$VAR" | Preserve whitespace and suppress glob expansion. |
'$VAR' | Treat $VAR literally; single quotes do no expansion. |
`cmd` | Legacy command substitution; prefer $(cmd). |
file="report final.txt"
if [[ -f "$file" ]]; then
printf 'Found: %s\n' "$file"
fi
Special parameters
Bash exposes useful information about the current command, process, and script arguments. $@ should normally be quoted as "$@" so each original argument remains separate.
| Parameter | Meaning |
|---|---|
$? | Exit status of the most recent pipeline or command. |
$! | PID of the most recent background job. |
$0 | Script or shell name. |
$1 … $9 | Positional arguments. |
$@ | All arguments, preserving boundaries when quoted. |
$# | Number of positional arguments. |
$$ | PID of the current shell. |
$- | Current shell option flags. |
printf 'script=%s args=%s\n' "$0" "$#"
for arg in "$@"; do
printf 'arg=%q\n' "$arg"
done
Redirection and pipes
Redirections are processed by the shell before a command runs. File descriptor 0 is standard input, 1 is standard output, and 2 is standard error.
| Syntax | Effect |
|---|---|
cmd > file | Write stdout, replacing the file. |
cmd >> file | Append stdout. |
cmd < file | Read stdin from a file. |
cmd 2> file | Write stderr separately. |
cmd 2>&1 | Send stderr to the current stdout destination. |
cmd &> file | Send stdout and stderr to one file in Bash. |
cmd1 | cmd2 | Pipe stdout of cmd1 into stdin of cmd2. |
cmd | tee file | Display output and save a copy. |
make 2>&1 | tee build.log
printf '%s\n' "$(< input.txt)" > output.txt
Use set -o pipefail in scripts when a failure inside a pipeline should make the whole pipeline fail.
Conditionals and tests
[[ ... ]] is Bash’s safer conditional expression syntax. It supports pattern matching and avoids many word-splitting surprises found with the older [ ... ] command.
if [[ -z ${1:-} ]]; then
printf 'usage: %s FILE\n' "$0" >&2
exit 2
elif [[ -r $1 && -f $1 ]]; then
printf 'Readable regular file\n'
else
printf 'Not a readable regular file\n' >&2
fi
| Test | Checks |
|---|---|
-e path | Path exists. |
-f path | Regular file. |
-d path | Directory. |
-r/-w/-x path | Readable, writable, or executable. |
-n string | Non-empty string. |
-z string | Empty string. |
a == b | String equality inside [[ ]]. |
n -gt 3 | Numeric comparison. |
Loops
Use for to iterate over words or arrays, while for a condition, and until for the inverse condition. Quote file paths and use -- where a command supports it.
for file in *.log; do
[[ -e $file ]] || continue
printf '%s: ' "$file"
wc -l < "$file"
done
while IFS= read -r line; do
printf '%s\n' "$line"
done < input.txt
for ((i = 1; i <= 3; i++)); do
printf 'attempt %d\n' "$i"
done
Practical one-liners
These recipes favor portable shell tools and explicit quoting. Replace the placeholder paths and patterns before running them on important data.
find . -type f -name '*.tmp' -print -delete
find . -type f -name '*.txt' -exec sed -i.bak 's/old/new/g' {} +
printf '%s\n' *.log | wc -l
while IFS= read -r file; do
printf '%s\n' "$file"
done < <(find . -type f -print)