Bash Cheatsheet
Tests and Conditionals
Use this Bash reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
[ ] — POSIX test Command
# Equivalent forms test -f file.txt [ -f file.txt ] # spaces around brackets are required # IMPORTANT: always quote variables [ "$var" = "value" ] # correct [ $var = value ] # WRONG: breaks if $var is empty or has spaces # Negate [ ! -f file.txt ] # Combine with -a (and), -o (or) — deprecated, use && / || instead [ -f file -a -r file ] # avoid [ -f file ] && [ -r file ] # preferred
[[ ]] — Bash Extended Test
# Double brackets: safer, more features [[ -f file.txt ]] [[ $var == "value" ]] # no quoting required for $var [[ $var != "other" ]] # Logical operators (not -a / -o) [[ $a -gt 0 && $b -lt 10 ]] [[ $x == "yes" || $x == "y" ]] [[ ! -d /tmp/missing ]] # Glob matching (only in [[ ]]) [[ $file == *.txt ]] [[ $name == foo* ]] [[ $name != *bar ]] # Regex matching (=~ only in [[ ]]) [[ $str =~ ^[0-9]+$ ]] [[ $email =~ @[a-zA-Z]+\.[a-zA-Z]{2,} ]] # Capture groups available in BASH_REMATCH [[ "2024-01-15" =~ ([0-9]{4})-([0-9]{2})-([0-9]{2}) ]] echo "${BASH_REMATCH[1]}" # 2024 echo "${BASH_REMATCH[2]}" # 01 echo "${BASH_REMATCH[3]}" # 15
(( )) — Arithmetic Test
(( 1 + 1 == 2 )) # true (exit 0) (( 0 )) # false (exit 1) (( 1 )) # true (exit 0) (( a > b )) # no $ needed inside (( )) (( a++ )) # side effect: increments a (( a = b + c )) # assignment inside arithmetic test if (( count > 0 )); then echo "positive" fi # Arithmetic boolean (( x > 0 && y < 10 )) (( x == 0 || y != 0 )) (( ! flag ))
File Test Operators
| Operator | True when |
|---|---|
-e file | file/dir/link exists |
-f file | regular file exists |
-d file | directory exists |
-L file | symbolic link exists |
-r file | readable |
-w file | writable |
-x file | executable |
-s file | exists and size > 0 |
-b file | block device |
-c file | character device |
-p file | named pipe (FIFO) |
-S file | socket |
-t fd | file descriptor is open terminal |
-N file | modified since last read |
-O file | owned by current user |
-G file | group-owned by current user's group |
f1 -nt f2 | f1 newer than f2 (mtime) |
f1 -ot f2 | f1 older than f2 (mtime) |
f1 -ef f2 | same file (hard links) |
[[ -f /etc/passwd && -r /etc/passwd ]] && cat /etc/passwd [[ -d "$dir" ]] || mkdir -p "$dir" [[ -x "$(command -v git)" ]] && echo "git available" [[ -t 1 ]] && echo "stdout is a terminal" # useful for coloring output
String Test Operators
| Operator | True when |
|---|---|
-z str | string is empty (zero length) |
-n str | string is non-empty |
s1 = s2 | equal (POSIX [ ]) |
s1 == s2 | equal (Bash [[ ]]) |
s1 != s2 | not equal |
s1 < s2 | s1 sorts before s2 (lexicographic) |
s1 > s2 | s1 sorts after s2 |
[[ -z "$var" ]] && echo "var is empty" [[ -n "$1" ]] || { echo "usage: $0 <arg>"; exit 1; } [[ "$name" == "root" ]] && echo "running as root"
Integer Test Operators
| Operator | Meaning |
|---|---|
n1 -eq n2 | equal |
n1 -ne n2 | not equal |
n1 -lt n2 | less than |
n1 -le n2 | less than or equal |
n1 -gt n2 | greater than |
n1 -ge n2 | greater than or equal |
[[ $count -gt 0 ]] && echo "non-zero" [[ $exit_code -ne 0 ]] && echo "failed" (( count > 0 )) && echo "non-zero" # arithmetic form (preferred)
Comparing [ ] vs [[ ]] vs (( ))
| Feature | [ ] | [[ ]] | (( )) |
|---|---|---|---|
| POSIX | yes | no | no |
| Glob matching | no | yes | no |
| Regex matching | no | yes (=~) | no |
| No quote needed | no | yes | yes |
| Arithmetic | -eq/-lt etc. | -eq/-lt etc. | C operators |
| Logical ops | -a/-o | && / || | && / || |
| Word splitting | yes | no | no |
# Prefer [[ ]] for strings, (( )) for numbers [[ -f "$file" && -n "$content" ]] && echo "ok" (( x > 0 && y < 100 )) && echo "in range"
Variable / Option Tests
# Check if variable is set (even if empty) [[ -v varname ]] # Bash 4.2+ [[ ${varname+x} ]] # portable alternative # Check if array element is set [[ -v arr[3] ]] # Check if shell option is set [[ -o errexit ]] # true if set -e is active [[ $- == *e* ]] # same, POSIX-ish # Check if a function is defined declare -f funcname > /dev/null && echo "defined" # Check if command exists command -v git > /dev/null && echo "git installed" type -t git > /dev/null # prints "file", "alias", "builtin", or "function"
Chaining Tests
# Short-circuit — common idioms [[ -f file ]] && echo "exists" [[ -d dir ]] || mkdir dir command_that_fails || exit 1 # Combine file and string tests [[ -f "$config" && -r "$config" && -s "$config" ]] || die "bad config" # Check multiple programs for cmd in git curl jq; do command -v "$cmd" > /dev/null || { echo "missing: $cmd"; exit 1; } done
BASH_REMATCH — Regex Captures
str="Date: 2024-12-25, Time: 14:30" regex='([0-9]{4}-[0-9]{2}-[0-9]{2})' if [[ $str =~ $regex ]]; then echo "Full match: ${BASH_REMATCH[0]}" # "2024-12-25" echo "Group 1: ${BASH_REMATCH[1]}" # "2024-12-25" fi # Multiple groups if [[ $str =~ ([0-9]{4})-([0-9]{2})-([0-9]{2}) ]]; then year="${BASH_REMATCH[1]}" # 2024 mon="${BASH_REMATCH[2]}" # 12 day="${BASH_REMATCH[3]}" # 25 fi # Note: store regex in variable to avoid quoting issues with [[ =~ ]]