Bash Scripting Cheatsheet
Bash is the most widely used shell scripting language on Linux and macOS. This cheatsheet organizes essential Bash scripting syntax by category — from variable assignment to job control — each with practical examples. Whether you're new to shell programming or need a quick reference, this guide has you covered.
Quick Reference
| Task | Syntax |
| Define a variable | name='value' |
| Conditional test | if [[ condition ]]; then |
| Numeric loop | for i in {1..10}; do |
| File loop | while read line; do |
| Define a function | function_name() { ... } |
| Create an array | arr=(a b c) |
| Read input | read -p "prompt" var |
| Command substitution | result=$(command) |
| Run in background | command & |
Variables
``bash
# Assignment and referencing
name='world' # String assignment (no spaces around =)
age=42 # Numeric assignment (quotes optional)
echo "Hello, $name" # Dollar-sign variable expansion
echo "Age is ${age}" # Brace form (for concatenation)
echo "${name}_suffix" # Concatenation: world_suffix
# Readonly variables readonly PI=3.14159 # Declare as read-only declare -r GRAVITY=9.8 # Alternative readonly syntax
# Delete a variable unset name # Delete/unset a variable
# Special variables
echo "$0" # Script name
echo "$1 $2 $3" # Positional parameters
echo "$#" # Number of arguments
echo "$@" # All arguments as list
echo "$?" # Exit code of last command (0=success)
echo "$$" # Current process PID
echo "$RANDOM" # Random number (0-32767)
`
Conditionals
`bash
# if / then / else / fi
if [[ $age -ge 18 ]]; then
echo "Adult"
elif [[ $age -ge 60 ]]; then
echo "Senior"
else
echo "Minor"
fi
# test command (POSIX compatible) if [ "$name" = "world" ]; then echo "Match" fi
# String comparison [[ "$name" == "world" ]] # Equal (pattern matching) [[ "$name" != "hello" ]] # Not equal [[ -z "$var" ]] # String is empty [[ -n "$var" ]] # String is non-empty
# Numeric comparison [[ $age -eq 42 ]] # Equal [[ $age -ne 0 ]] # Not equal [[ $age -gt 18 ]] # Greater than [[ $age -ge 18 ]] # Greater or equal [[ $age -lt 60 ]] # Less than [[ $age -le 60 ]] # Less or equal
# File tests [[ -f "file.txt" ]] # Is a regular file [[ -d "dir/" ]] # Is a directory [[ -e "path" ]] # Path exists [[ -s "file" ]] # File is non-empty [[ -r "file" ]] # File is readable [[ -w "file" ]] # File is writable [[ -x "file" ]] # File is executable
# Logical operators [[ -n "$var" && $age -gt 0 ]] # AND [[ -z "$var" || $age -eq 0 ]] # OR [[ ! -f "file" ]] # NOT
# case statement
case "$os" in
linux|Linux)
echo "Linux system"
;;
darwin|macos)
echo "macOS system"
;;
*)
echo "Unknown system"
;;
esac
`
Loops
`bash
# for loop (numeric range)
for i in {1..5}; do
echo "Number: $i"
done
# for loop (list) for fruit in apple banana orange; do echo "Fruit: $fruit" done
# for loop (C-style) for (( i=0; i
# for loop (globbing) for file in *.sh; do echo "Script: $file" done
# while loop count=1 while [[ $count -le 5 ]]; do echo "Count: $count" ((count++)) done
# while read line by line while IFS= read -r line; do echo "Line: $line" done < input.txt
# until loop until [[ $count -gt 5 ]]; do echo "count = $count" ((count++)) done
# break and continue
for i in {1..10}; do
[[ $i -eq 3 ]] && continue # Skip 3
[[ $i -eq 8 ]] && break # Stop at 8
echo "i = $i"
done
# Output: 1 2 4 5 6 7
`
Functions
`bash
# Simple function definition
greet() {
echo "Hello, $1!"
}
# Call the function greet "Alice" # Output: Hello, Alice!
# Function with return add() { local a=$1 b=$2 return $((a + b)) } add 3 4 echo "$?" # Output: 7 (return is 0-255 limited)
# Function with result via echo (preferred) multiply() { local a=$1 b=$2 echo $((a * b)) # Use echo to return result } result=$(multiply 6 7) echo "$result" # Output: 42
# local variables myfunc() { local local_var="visible inside function only" global_var="visible everywhere" echo "$local_var" }
# Default parameter values say_hello() { local name=${1:-"World"} # Default: World echo "Hello, $name" }
# Getting all parameters
print_args() {
for arg in "$@"; do
echo "Argument: $arg"
done
}
`
Arrays
`bash
# Define arrays
fruits=("apple" "banana" "orange")
numbers=(1 2 3 4 5)
# Index access echo "${fruits[0]}" # Output: apple echo "${fruits[-1]}" # Output: orange (last element)
# All elements echo "${fruits[@]}" # All elements (space-separated) echo "${fruits[*]}" # All elements (IFS-joined)
# Array length echo "${#fruits[@]}" # Output: 3
# Adding elements fruits+=("grape") # Append fruits[10]="kiwi" # Indexed insert (array auto-expands)
# Deleting elements unset fruits[1] # Delete index 1 (banana) unset fruits # Delete entire array
# Slicing arr=(a b c d e) echo "${arr[@]:1:3}" # Output: b c d (3 elements from index 1) echo "${arr[@]:2}" # From index 2 to end
# Associative arrays (Bash 4+)
declare -A user
user[name]="Alice"
user[age]=30
user[city]="Beijing"
echo "${user[name]}" # Output: Alice
echo "${!user[@]}" # All keys: name age city
`
I/O Operations
`bash
# echo output
echo "Hello World" # Newline by default
echo -n "No newline" # -n suppresses trailing newline
echo -e "Tab:\there" # -e enables escape sequences
# printf formatted output printf "Name: %s, Count: %d\\n" "Apple" 5
# read input read -p "Enter name: " name # Prompt for input read -s -p "Password: " pass # -s for silent input (passwords) read -t 5 -p "5s timeout: " var # -t timeout in seconds
# Redirection command > file # stdout to file (overwrite) command >> file # stdout to file (append) command 2> error.log # stderr to file command &> output.log # stdout + stderr combined command < input.txt # file as stdin
# Pipes cmd1 | cmd2 # cmd1 output feeds cmd2 input
# Here Document cat << EOF Multi-line text Variables like $HOME are expanded EOF
# Here String grep "abc" <<< "abcdef" # string as stdin
# tee (split output to screen and file)
echo "Log entry" | tee log.txt
`
Substitution & Expansion
`bash
# Command substitution (two equivalent syntaxes)
today=$(date +%Y-%m-%d) # Modern: $(...) — recommended
today2=date +%Y-%m-%d # Legacy: backticks
# Arithmetic expansion echo $((5 + 3 * 2)) # Output: 11 echo $(( (a + b) % 10 )) # Using variables num=$((RANDOM % 100 + 1)) # Random 1-100
# let command let "x = 10" let "x += 5"
# Parameter expansion — default values echo "${var:-default}" # If unset/null, use default (var unchanged) echo "${var:=default}" # If unset/null, assign default and return echo "${var:?error msg}" # If unset/null, print error and exit echo "${var:+replacement}" # If set/non-null, use replacement
# Parameter expansion — string operations echo "${#str}" # String length echo "${str:0:3}" # Substring (3 chars from index 0) echo "${str#prefix}" # Remove shortest leading prefix echo "${str##prefix}" # Remove longest leading prefix echo "${str%suffix}" # Remove shortest trailing suffix echo "${str%%suffix}" # Remove longest trailing suffix echo "${str/a/b}" # Replace first match echo "${str//a/b}" # Replace all matches echo "${str^^}" # Uppercase echo "${str,,}" # Lowercase
# Brace expansion echo {a,b,c}.txt # Output: a.txt b.txt c.txt echo {1..5} # Output: 1 2 3 4 5 echo {01..10} # Output: 01 02 ... 10 echo file{1..3}.txt # Output: file1.txt file2.txt file3.txt
# Process substitution
diff <(ls dir1) <(ls dir2) # Compare directory listings
`
Job Control
`bash
# Background execution
sleep 100 & # Run in background (returns job ID & PID)
# List background jobs jobs # List all background jobs jobs -l # List jobs with PIDs
# Foreground / Background switching fg %1 # Bring job 1 to foreground bg %1 # Resume suspended job 1 in background
# Suspend and terminate Ctrl+z # Suspend current foreground process Ctrl+c # Terminate current foreground process kill %1 # Terminate job 1 kill -9 1234 # Force kill PID 1234
# nohup (survive terminal close) nohup long-task.sh & # Process continues after terminal exit
# disown (detach from shell) command & disown # Remove from job table (no SIGHUP on exit)
# trap (signal handling) cleanup() { echo "Cleaning up temp files..." rm -rf /tmp/temp_* } trap cleanup EXIT # Run cleanup on script exit trap 'echo "Ctrl+C pressed"' INT # Handle Ctrl+C trap 'echo "Term signal received"' TERM # Handle SIGTERM ``
Variable Ops(4)
| Command | Level | ||
|---|---|---|---|
name=valueVariable assignment (no spaces around =) | Basic | name='world' | |
readonly / declare -rDeclare a read-only variable | Intermediate | readonly PI=3.14159 | |
unsetDelete a variable or array element | Basic | unset name | |
$0 $1 $# $@ $?Special variables — script name, args, count, exit code | Intermediate | echo "$0 $# $?" |
Conditionals(6)
| Command | Level | ||
|---|---|---|---|
if [[ condition ]]; then ... fiConditional statement (double brackets, supports pattern matching) | Basic | if [[ $age -ge 18 ]]; then echo "Adult"; fi
| |
[ condition ]POSIX-compatible test expression | Basic | [ "$name" = "world" ] | |
-eq / -ne / -gt / -lt / -ge / -leNumeric comparison operators | Basic | [[ $age -gt 18 ]] | |
-f / -d / -e / -r / -w / -xFile test operators | Intermediate | [[ -f "file.txt" ]] | |
&& / || / !Logical AND, OR, NOT | Intermediate | [[ -n "$var" && $age -gt 0 ]] | |
case ... esacMulti-branch conditional matching | Intermediate | case "$os" in linux|Linux) echo "Linux";; *) echo "Other";; esac
|
Loops(5)
| Command | Level | ||
|---|---|---|---|
for i in {1..5}; do ... doneFor loop (numeric range) | Basic | for i in {1..5}; do echo $i; done | |
for (( i=0; i<5; i++ )); do ... doneC-style for loop | Intermediate | for (( i=0; i<5; i++ )); do echo $i; done | |
while [[ condition ]]; do ... doneWhile conditional loop | Basic | while [[ $count -le 5 ]]; do echo $count; ((count++)); done | |
until [[ condition ]]; do ... doneUntil conditional loop (executes while condition is false) | Intermediate | until [[ $count -gt 5 ]]; do echo $count; ((count++)); done | |
break / continueExit loop / skip current iteration | Intermediate | for i in {1..10}; do [[ $i -eq 3 ]] && continue; done |
Functions(4)
| Command | Level | ||
|---|---|---|---|
function_name() { ... }Define a function | Basic | greet() { echo "Hello, $1!"; } | |
local var=valueDeclare a local variable (visible inside function only) | Intermediate | local name=$1 | |
returnReturn from a function (integer exit code 0-255) | Intermediate | return $((a + b)) | |
${1:-default}Default value for function parameters | Intermediate | local name=${1:-"World"} |
Arrays(4)
| Command | Level | ||
|---|---|---|---|
arr=(a b c)Define an indexed array | Basic | fruits=("apple" "banana" "orange") | |
${arr[@]} / ${#arr[@]}All array elements / array length | Basic | echo "${fruits[@]}" | |
arr+=("item")Append elements to an array | Intermediate | fruits+=("grape") | |
declare -A mapDefine an associative array (Bash 4+) | Expert | declare -A user; user[name]="Alice" |
I/O(6)
| Command | Level | ||
|---|---|---|---|
echoOutput text to stdout | Basic | echo -e "Tab:\there" | |
printfFormatted output (similar to C printf) | Intermediate | printf "Name: %s, Count: %d\\n" "Apple" 5 | |
readRead from stdin | Basic | read -p "Enter name: " name | |
> / >> / 2> / &> / <I/O redirection operators | Basic | command &> output.log | |
|Pipe — send stdout of one command to stdin of another | Basic | cmd1 | cmd2 | |
cat << EOFHere Document — multi-line input | Intermediate | cat << EOF\\n多行文本\\nEOF |
Substitution(6)
| Command | Level | ||
|---|---|---|---|
$(command)Command substitution — capture command output into variable | Basic | today=$(date +%Y-%m-%d) | |
$(( arithmetic ))Arithmetic expansion — evaluate integer expression | Basic | echo $((5 + 3 * 2)) | |
${var:-default} / ${var:=default} / ${var:?err}Parameter expansion — default value, assign default, error exit | Intermediate | echo "${var:-default}" | |
${#str} / ${str:0:3} / ${str//a/b} / ${str^^}Parameter expansion — length, substring, replace, case conversion | Intermediate | echo "${str//old/new}" | |
{a,b,c} / {1..10}Brace expansion — generate string sequences | Intermediate | echo {a,b,c}.txt | |
<(command)Process substitution — pass command output as a file | Expert | diff <(ls dir1) <(ls dir2) |
Job Control(6)
| Command | Level | ||
|---|---|---|---|
command &Run a command in the background | Basic | sleep 100 & | |
jobsList background jobs in the current shell | Basic | jobs -l | |
fg / bgBring job to foreground / resume in background | Intermediate | fg %1 | |
killTerminate a process or job | Intermediate | kill -9 1234 | |
nohupRun a process immune to SIGHUP (survives terminal close) | Intermediate | nohup long-task.sh & | |
trapTrap signals and execute custom handlers | Expert | trap cleanup EXIT |