Bash 5.3 Reference
Overview
Complete reference for GNU Bash 5.3 (May 2025). Covers all shell syntax, builtins, variables, expansions, redirections, and features. Use this skill whenever writing or reviewing bash scripts to ensure correctness.
This file is a scannable hub. Each section below summarizes key constructs with compact tables. Use the Read tool to load referenced files identified as relevant for full syntax, edge cases, and examples:
- Syntax & commands (quoting, compound commands, pipelines):
shell-syntax-and-commands.md
- Functions, parameters & expansions (all expansion types, pattern matching):
functions-parameters-expansions.md
- Redirections & execution (I/O, here docs, FDs, command search, signals):
redirections-and-execution.md
- Builtins (
set, shopt, declare, read, printf, trap, etc.): shell-builtins.md
- Variables (
BASH_REMATCH, PIPESTATUS, EPOCHSECONDS, etc.): shell-variables.md
- Bash features (startup files, arrays, arithmetic, POSIX mode, conditionals):
bash-features.md
- Job control, readline & history (bg/fg, completion, history expansion):
job-control-readline-history.md
When to Use
- Need exact syntax for any Bash construct (loops, conditionals, expansions, redirections)
- Writing, reviewing, or debugging Bash scripts
- Unsure about quoting rules, expansion order, or operator behavior
- Need to look up a specific builtin, variable, shopt option, or test operator
- Verifying Bash 5.3-specific features (
${ command; }, GLOBSORT, BASH_MONOSECONDS)
When NOT to Use
- Writing POSIX-portable
sh scripts (this covers Bash-specific features beyond POSIX)
- Zsh, Fish, or other shell syntax
- Structuring multi-file Bash projects (use
bash_clean_architecture instead)
Reference Files
| File |
Contents |
shell-syntax-and-commands.md |
Quoting, comments, reserved words, pipelines, lists, compound commands (if/for/while/case/select/[[/(( ), grouping, coprocesses |
functions-parameters-expansions.md |
Shell functions, positional/special parameters, ALL expansion types (brace, tilde, parameter, command substitution, arithmetic, process substitution, word splitting, globbing, pattern matching) |
redirections-and-execution.md |
All redirection types, here docs/strings, file descriptors, command search/execution, execution environment, exit status, signals, shell scripts |
shell-builtins.md |
All Bourne shell builtins, all Bash builtins, set options, shopt options, special builtins |
shell-variables.md |
All Bourne shell variables, all Bash variables (BASH_*, COMP_*, HIST*, READLINE_*, etc.) |
bash-features.md |
Invocation options, startup files, interactive shell behavior, conditional expressions, arithmetic, aliases, arrays, directory stack, prompt control, restricted shell, POSIX mode, compatibility mode |
job-control-readline-history.md |
Job control (bg/fg/jobs/disown), readline configuration, all bindable commands, vi mode, programmable completion (complete/compgen/compopt), history expansion |
Which File Do I Need?
| I need to... |
Read |
| Write a function, use parameters/expansions, do string manipulation |
functions-parameters-expansions.md |
Use if/for/while/case/select/[[ ]]/(( )), or understand quoting |
shell-syntax-and-commands.md |
| Redirect I/O, use here docs/strings, understand fd management |
redirections-and-execution.md |
Look up a builtin (set, shopt, declare, read, printf, trap, etc.) |
shell-builtins.md |
Check a shell variable (BASH_REMATCH, PIPESTATUS, EPOCHSECONDS, etc.) |
shell-variables.md |
| Understand startup files, arrays, arithmetic, POSIX mode, or conditional expressions |
bash-features.md |
| Work with job control, readline, completion, or history expansion |
job-control-readline-history.md |
Quick Reference: Most-Used Constructs
Quoting
Full details: shell-syntax-and-commands.md (section 1)
| Syntax |
Behavior |
\x |
Escape single character |
'text' |
Literal string, no expansion |
"text" |
Allows $, `, \, ! expansion |
$'text' |
ANSI-C escapes: \n, \t, \e, \xHH, \uHHHH, \UHHHHHHHH |
$"text" |
Locale-specific translation |
Parameter Expansion
Full details: functions-parameters-expansions.md (section 3.4)
| Syntax |
Result |
${var:-default} |
Use default if var unset/null |
${var:=default} |
Assign default if var unset/null |
${var:+alternate} |
Use alternate if var IS set |
${var:?error} |
Error if var unset/null |
${#var} |
String length |
${var:offset:length} |
Substring |
${var#pattern} |
Remove shortest prefix match |
${var##pattern} |
Remove longest prefix match |
${var%pattern} |
Remove shortest suffix match |
${var%%pattern} |
Remove longest suffix match |
${var/pat/str} |
Replace first match |
${var//pat/str} |
Replace all matches |
${var/#pat/str} |
Replace if matches beginning |
${var/%pat/str} |
Replace if matches end |
${var^pattern} |
Uppercase first char |
${var^^pattern} |
Uppercase all chars |
${var,pattern} |
Lowercase first char |
${var,,pattern} |
Lowercase all chars |
${!prefix*} |
Names matching prefix |
${!name[@]} |
Array indices/keys |
${!var} |
Indirect expansion |
${var@Q} |
Quote for reuse |
${var@E} |
Expand escape sequences |
${var@P} |
Expand as prompt string |
${var@A} |
Assignment statement form |
${var@a} |
Attribute flags |
${var@U} |
Uppercase all |
${var@u} |
Uppercase first |
${var@L} |
Lowercase all |
${var@K} |
Key-value pairs (assoc arrays) |
Special Parameters
Full details: functions-parameters-expansions.md (section 2)
| Param |
Meaning |
$0 |
Script/shell name |
$1..$9, ${10} |
Positional parameters |
$# |
Number of positional parameters |
$* |
All positional params as single word (with IFS) |
$@ |
All positional params as separate words |
"$*" |
"$1c$2c..." where c = first char of IFS |
"$@" |
"$1" "$2" ... (preserves word boundaries) |
$? |
Exit status of last command |
$$ |
PID of the shell |
$! |
PID of last background command |
$- |
Current option flags |
$_ |
Last argument of previous command |
Compound Commands
Full details: shell-syntax-and-commands.md (section 3)
# If
if cmd; then ...; elif cmd; then ...; else ...; fi
# For
for var in words; do ...; done
for (( init; test; step )); do ...; done
# While / Until
while cmd; do ...; done
until cmd; do ...; done
# Case
case word in
pattern1|pattern2) commands ;; # break
pattern3) commands ;& # fall-through
pattern4) commands ;;& # test next
esac
# Select (menu)
select var in words; do ...; done
# Test
[[ expression ]] # Preferred (no word splitting/globbing)
(( expression )) # Arithmetic evaluation
# Grouping
{ commands; } # Current shell (note: space after {, ; before })
( commands ) # Subshell
Test Operators ([[ ]] and test/[ ])
Full details: bash-features.md (section 4)
| Operator |
Test |
-e file |
Exists |
-f file |
Regular file |
-d file |
Directory |
-L file / -h file |
Symlink |
-s file |
Non-zero size |
-r file |
Readable |
-w file |
Writable |
-x file |
Executable |
-p file |
Named pipe |
-S file |
Socket |
-b file |
Block device |
-c file |
Character device |
-t fd |
FD is terminal |
-O file |
Owned by effective UID |
-G file |
Owned by effective GID |
-N file |
Modified since last read |
f1 -nt f2 |
f1 newer than f2 |
f1 -ot f2 |
f1 older than f2 |
f1 -ef f2 |
Same inode |
-v var |
Variable is set |
-R var |
Variable is nameref |
-z string |
Zero length |
-n string |
Non-zero length |
s1 == s2 |
Equal (pattern match in [[ ]]) |
s1 != s2 |
Not equal |
s1 < s2 |
Less than (lexicographic) |
s1 > s2 |
Greater than (lexicographic) |
s1 =~ regex |
Regex match ([[ ]] only) |
n1 -eq n2 |
Numeric equal |
n1 -ne n2 |
Numeric not equal |
n1 -lt n2 |
Numeric less than |
n1 -le n2 |
Numeric less/equal |
n1 -gt n2 |
Numeric greater than |
n1 -ge n2 |
Numeric greater/equal |
Redirections
Full details: redirections-and-execution.md (section 1)
| Syntax |
Operation |
cmd < file |
Stdin from file |
cmd > file |
Stdout to file (truncate) |
cmd >> file |
Stdout to file (append) |
cmd 2> file |
Stderr to file |
cmd &> file or cmd > file 2>&1 |
Stdout+stderr to file |
cmd &>> file or cmd >> file 2>&1 |
Stdout+stderr append |
cmd >| file |
Force overwrite (noclobber) |
cmd <<EOF |
Here document |
cmd <<-EOF |
Here document (strip leading tabs) |
cmd <<< "string" |
Here string |
cmd <&fd |
Duplicate input FD |
cmd >&fd |
Duplicate output FD |
cmd fd<&- |
Close input FD |
cmd fd>&- |
Close output FD |
cmd n<>file |
Open for read+write on FD n |
cmd {var}> file |
Auto-assign FD to var |
Special filenames in redirections: /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr, /dev/tcp/host/port, /dev/udp/host/port
Arrays
Full details: bash-features.md (section 6)
# Indexed arrays
declare -a arr=(one two three)
arr[0]="value"
arr+=(more items)
# Associative arrays (Bash 4.0+)
declare -A map=([key1]=val1 [key2]=val2)
map[key]="value"
# Access
${arr[0]} # Single element
${arr[@]} # All elements (separate words)
${arr[*]} # All elements (single word with IFS)
${#arr[@]} # Number of elements
${!arr[@]} # All indices/keys
${arr[@]:off:len} # Slice
# Unset
unset 'arr[2]' # Remove element (quote to prevent glob)
unset arr # Remove entire array
Expansion Order
- Brace expansion
- Tilde expansion
- Parameter and variable expansion
- Arithmetic expansion
- Command substitution (left-to-right)
- Process substitution
- Word splitting
- Filename expansion (globbing)
- Quote removal
Steps 2-6 happen left-to-right simultaneously. Full details with word-count impacts: functions-parameters-expansions.md (section 3.5).
Common set Options
Full details: shell-builtins.md (section 2, set builtin)
| Option |
Effect |
set -e (errexit) |
Exit on error (with exceptions) |
set -u (nounset) |
Error on unset variables |
set -o pipefail |
Pipeline fails if any command fails |
set -x (xtrace) |
Print commands before execution |
set -f (noglob) |
Disable filename expansion |
set -n (noexec) |
Read commands without executing (syntax check) |
set -o posix |
POSIX compliance mode |
set -E (errtrace) |
ERR trap inherited by functions |
set -T (functrace) |
DEBUG/RETURN traps inherited by functions |
Essential shopt Options
Full details: shell-builtins.md (section 3, shopt options)
| Option |
Effect |
extglob |
Extended patterns: ?(pat) *(pat) +(pat) @(pat) !(pat) |
globstar |
** matches directories recursively |
nullglob |
Unmatched globs expand to nothing |
failglob |
Unmatched globs cause error |
nocaseglob |
Case-insensitive globbing |
nocasematch |
Case-insensitive case and [[ == ]] |
dotglob |
Globs match dotfiles |
lastpipe |
Last pipeline command runs in current shell |
inherit_errexit |
Command substitutions inherit errexit |
assoc_expand_once |
Expand associative array subscripts once |
Trap Signals
Full details: shell-builtins.md (trap builtin) and redirections-and-execution.md (section 5, Signals)
trap 'cleanup' EXIT # On shell exit
trap 'handle_err' ERR # On command error (with set -e)
trap 'on_debug' DEBUG # Before every command
trap 'on_return' RETURN # After function/sourced script returns
trap 'handle_int' INT # Ctrl-C
trap 'handle_term' TERM # kill signal
trap '' SIGNAL # Ignore signal
trap - SIGNAL # Reset to default
Arithmetic Operators (inside (( )) and $(( )))
Full details: bash-features.md (section 5)
All C-style operators: +, -, *, /, %, ** (exponent), <<, >>, &, |, ^, ~, !, &&, ||, <, >, <=, >=, ==, !=, =, +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=, ++, --, expr?expr:expr (ternary), expr,expr (comma)
Bases: 0x (hex), 0 (octal), 0b (binary), base#number (arbitrary base 2-64)
Prompt Escape Sequences
Full details: bash-features.md (section 8, Controlling the Prompt)
| Escape |
Meaning |
\u |
Username |
\h |
Hostname (short) |
\H |
Hostname (full) |
\w |
Working directory |
\W |
Basename of working directory |
\d |
Date (Day Mon Date) |
\t |
Time (HH:MM:SS 24hr) |
\T |
Time (HH:MM:SS 12hr) |
\@ |
Time (AM/PM) |
\A |
Time (HH:MM 24hr) |
\D{fmt} |
strftime format |
\j |
Number of jobs |
\! |
History number |
\# |
Command number |
\$ |
# if root, $ otherwise |
\[ |
Begin non-printing chars |
\] |
End non-printing chars |
Definitions
| Term |
Definition |
| blank |
Space or tab |
| word |
Sequence of characters treated as a unit (no unquoted metacharacters) |
| token |
A word or an operator |
| metacharacter |
Unquoted: space, tab, newline, |, &, ;, (, ), <, > |
| control operator |
||, &&, &, ;, ;;, ;&, ;;&, |, |&, (, ), newline |
| name/identifier |
Letters, numbers, underscores; starts with letter or underscore |
| exit status |
0-255; 0 = success, 1 = general error, 2 = usage error, 126 = not executable, 127 = not found, 128+N = killed by signal N |
| special builtin |
POSIX-designated builtins that have special properties (break, :, ., continue, eval, exec, exit, export, readonly, return, set, shift, trap, unset) |
Common Patterns
Safe Script Header
#!/usr/bin/env bash
set -euo pipefail
Temporary Files
tmpfile=$(mktemp) || exit 1
trap 'rm -f "$tmpfile"' EXIT
Read File Line by Line
while IFS= read -r line; do
printf '%s\n' "$line"
done < "$file"
Default Values
name="${1:-default}" # Use default if $1 unset/empty
name="${1:?'missing arg'}" # Exit with error if $1 unset/empty
String Operations
# Lowercase / Uppercase
lower="${str,,}"
upper="${str^^}"
first_cap="${str^}"
# Trim prefix/suffix
filename="${path##*/}" # basename
dir="${path%/*}" # dirname
ext="${file##*.}" # extension
noext="${file%.*}" # remove extension
Array Iteration
for item in "${arr[@]}"; do echo "$item"; done # values
for i in "${!arr[@]}"; do echo "$i: ${arr[$i]}"; done # index: value
Process Substitution
diff <(sort file1) <(sort file2)
while IFS= read -r line; do ...; done < <(cmd) # avoid subshell
Associative Array Check
declare -A map
if [[ -v map["key"] ]]; then echo "exists"; fi
Common Mistakes
Unquoted variables (word splitting + globbing)
# BAD: word splits and globs if file contains spaces or wildcards
for f in $files; do rm $f; done
# GOOD: always quote variable expansions
for f in "${files[@]}"; do rm "$f"; done
[ ] vs [[ ]]
# BAD: word splitting inside [ ] can break with spaces in $var
[ $var == "hello" ] # also: == is not POSIX in [ ]
# GOOD: [[ ]] prevents word splitting and supports == and =~
[[ $var == "hello" ]]
$@ vs $* quoting
# BAD: loses word boundaries
for arg in $@; do echo "$arg"; done
# GOOD: preserves each argument as a separate word
for arg in "$@"; do echo "$arg"; done
# "$*" joins all args into ONE word (separated by first char of IFS)
set -e doesn't trigger everywhere
set -e
# These do NOT cause exit on failure:
if false; then :; fi # test in 'if'
false || true # LHS of ||
false && true # LHS of &&
false | true # pipeline (without pipefail)
! false # negated command
Missing ; before } in brace groups
# BAD: syntax error
{ echo "hello" }
# GOOD: semicolon (or newline) required before }
{ echo "hello"; }
Array access without braces
arr=(one two three)
# BAD: expands $arr (element 0) then appends literal [1]
echo $arr[1] # prints: one[1]
# GOOD: braces required for array subscript
echo "${arr[1]}" # prints: two
Forgetting declare -A for associative arrays
# BAD: creates an indexed array, keys treated as arithmetic (0)
map=([foo]=1 [bar]=2)
echo "${map[foo]}" # prints: 2 (both keys evaluated to index 0)
# GOOD: must declare associative arrays explicitly
declare -A map=([foo]=1 [bar]=2)
echo "${map[foo]}" # prints: 1
Using = vs == in the wrong context
# In [ ] / test: use = (POSIX). == works in Bash but is not portable.
[ "$a" = "$b" ]
# In [[ ]]: both = and == work; RHS is a pattern (quote for literal match)
[[ "$a" == "$b" ]] # literal match (RHS quoted)
[[ "$a" == "$b"* ]] # glob pattern (unquoted * appended)
[[ "$a" == $b ]] # if $b contains *, it's a pattern (RHS unquoted)
Subshell variable loss in pipes
# BAD: read runs in subshell, $var is lost after pipeline
echo "hello" | read var
echo "$var" # empty
# GOOD: use process substitution or lastpipe
read var < <(echo "hello")
echo "$var" # hello
# OR: enable lastpipe (non-interactive, no job control)
shopt -s lastpipe
echo "hello" | read var
local variables use dynamic scoping
inner() { echo "$x"; }
outer() { local x=42; inner; }
outer # prints: 42 (inner sees outer's local!)
# This is dynamic scoping, not lexical. Any function called
# from a scope with a local variable sees that variable.
Here-strings always append a trailing newline
read -r var <<< "hello"
printf '%s' "$var" | xxd # contains "hello\n" — trailing newline added
# Use printf instead when exact bytes matter:
read -r var < <(printf '%s' "hello")
declare -i silently evaluates strings as arithmetic
declare -i num
num="1+1"
echo "$num" # prints: 2 (string was evaluated!)
# WARNING: with untrusted input this is a code injection vector:
# declare -i x; x="a]$(cmd)" would execute cmd
trap EXIT is reset in subshells
trap 'echo cleanup' EXIT
(echo "subshell") # EXIT trap does NOT fire here
# Subshells inherit the parent's traps but reset EXIT/ERR/DEBUG/RETURN.
# If you need cleanup in a subshell, set a new trap inside it.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: bx-bash-reference3description: Use when writing, reviewing, or debugging Bash scripts, when needing exact syntax for shell constructs, parameter expansions, redirections, builtins, test expressions, arrays, or any Bash 5.3 feature. Use when unsure about quoting rules, expansion order, conditional operators, trap behavior, shopt options, or specific builtin options and arguments.4---56# Bash 5.3 Reference78## Overview910Complete reference for GNU Bash 5.3 (May 2025). Covers all shell syntax, builtins, variables, expansions, redirections, and features. Use this skill whenever writing or reviewing bash scripts to ensure correctness.1112**This file is a scannable hub.** Each section below summarizes key constructs with compact tables. Use the Read tool to load referenced files identified as relevant for full syntax, edge cases, and examples:1314- **Syntax & commands** (quoting, compound commands, pipelines): `shell-syntax-and-commands.md`15- **Functions, parameters & expansions** (all expansion types, pattern matching): `functions-parameters-expansions.md`16- **Redirections & execution** (I/O, here docs, FDs, command search, signals): `redirections-and-execution.md`17- **Builtins** (`set`, `shopt`, `declare`, `read`, `printf`, `trap`, etc.): `shell-builtins.md`18- **Variables** (`BASH_REMATCH`, `PIPESTATUS`, `EPOCHSECONDS`, etc.): `shell-variables.md`19- **Bash features** (startup files, arrays, arithmetic, POSIX mode, conditionals): `bash-features.md`20- **Job control, readline & history** (bg/fg, completion, history expansion): `job-control-readline-history.md`2122## When to Use2324- Need exact syntax for any Bash construct (loops, conditionals, expansions, redirections)25- Writing, reviewing, or debugging Bash scripts26- Unsure about quoting rules, expansion order, or operator behavior27- Need to look up a specific builtin, variable, shopt option, or test operator28- Verifying Bash 5.3-specific features (`${ command; }`, `GLOBSORT`, `BASH_MONOSECONDS`)2930## When NOT to Use3132- Writing POSIX-portable `sh` scripts (this covers Bash-specific features beyond POSIX)33- Zsh, Fish, or other shell syntax34- Structuring multi-file Bash projects (use `bash_clean_architecture` instead)3536## Reference Files3738| File | Contents |39|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|40| `shell-syntax-and-commands.md` | Quoting, comments, reserved words, pipelines, lists, compound commands (if/for/while/case/select/[[/(( ), grouping, coprocesses |41| `functions-parameters-expansions.md` | Shell functions, positional/special parameters, ALL expansion types (brace, tilde, parameter, command substitution, arithmetic, process substitution, word splitting, globbing, pattern matching) |42| `redirections-and-execution.md` | All redirection types, here docs/strings, file descriptors, command search/execution, execution environment, exit status, signals, shell scripts |43| `shell-builtins.md` | All Bourne shell builtins, all Bash builtins, `set` options, `shopt` options, special builtins |44| `shell-variables.md` | All Bourne shell variables, all Bash variables (BASH_*, COMP_*, HIST*, READLINE_*, etc.) |45| `bash-features.md` | Invocation options, startup files, interactive shell behavior, conditional expressions, arithmetic, aliases, arrays, directory stack, prompt control, restricted shell, POSIX mode, compatibility mode |46| `job-control-readline-history.md` | Job control (bg/fg/jobs/disown), readline configuration, all bindable commands, vi mode, programmable completion (complete/compgen/compopt), history expansion |4748### Which File Do I Need?4950| I need to... | Read |51|--------------------------------------------------------------------------------------|--------------------------------------|52| Write a function, use parameters/expansions, do string manipulation | `functions-parameters-expansions.md` |53| Use `if`/`for`/`while`/`case`/`select`/`[[ ]]`/`(( ))`, or understand quoting | `shell-syntax-and-commands.md` |54| Redirect I/O, use here docs/strings, understand fd management | `redirections-and-execution.md` |55| Look up a builtin (`set`, `shopt`, `declare`, `read`, `printf`, `trap`, etc.) | `shell-builtins.md` |56| Check a shell variable (`BASH_REMATCH`, `PIPESTATUS`, `EPOCHSECONDS`, etc.) | `shell-variables.md` |57| Understand startup files, arrays, arithmetic, POSIX mode, or conditional expressions | `bash-features.md` |58| Work with job control, readline, completion, or history expansion | `job-control-readline-history.md` |596061## Quick Reference: Most-Used Constructs6263### Quoting6465> Full details: `shell-syntax-and-commands.md` (section 1)6667| Syntax | Behavior |68|-----------|------------------------------------------------------------------|69| `\x` | Escape single character |70| `'text'` | Literal string, no expansion |71| `"text"` | Allows `$`, `` ` ``, `\`, `!` expansion |72| `$'text'` | ANSI-C escapes: `\n`, `\t`, `\e`, `\xHH`, `\uHHHH`, `\UHHHHHHHH` |73| `$"text"` | Locale-specific translation |7475### Parameter Expansion7677> Full details: `functions-parameters-expansions.md` (section 3.4)7879| Syntax | Result |80|------------------------|----------------------------------|81| `${var:-default}` | Use default if var unset/null |82| `${var:=default}` | Assign default if var unset/null |83| `${var:+alternate}` | Use alternate if var IS set |84| `${var:?error}` | Error if var unset/null |85| `${#var}` | String length |86| `${var:offset:length}` | Substring |87| `${var#pattern}` | Remove shortest prefix match |88| `${var##pattern}` | Remove longest prefix match |89| `${var%pattern}` | Remove shortest suffix match |90| `${var%%pattern}` | Remove longest suffix match |91| `${var/pat/str}` | Replace first match |92| `${var//pat/str}` | Replace all matches |93| `${var/#pat/str}` | Replace if matches beginning |94| `${var/%pat/str}` | Replace if matches end |95| `${var^pattern}` | Uppercase first char |96| `${var^^pattern}` | Uppercase all chars |97| `${var,pattern}` | Lowercase first char |98| `${var,,pattern}` | Lowercase all chars |99| `${!prefix*}` | Names matching prefix |100| `${!name[@]}` | Array indices/keys |101| `${!var}` | Indirect expansion |102| `${var@Q}` | Quote for reuse |103| `${var@E}` | Expand escape sequences |104| `${var@P}` | Expand as prompt string |105| `${var@A}` | Assignment statement form |106| `${var@a}` | Attribute flags |107| `${var@U}` | Uppercase all |108| `${var@u}` | Uppercase first |109| `${var@L}` | Lowercase all |110| `${var@K}` | Key-value pairs (assoc arrays) |111112### Special Parameters113114> Full details: `functions-parameters-expansions.md` (section 2)115116| Param | Meaning |117|---------------------|-------------------------------------------------|118| `$0` | Script/shell name |119| `$1`..`$9`, `${10}` | Positional parameters |120| `$#` | Number of positional parameters |121| `$*` | All positional params as single word (with IFS) |122| `$@` | All positional params as separate words |123| `"$*"` | `"$1c$2c..."` where c = first char of IFS |124| `"$@"` | `"$1" "$2" ...` (preserves word boundaries) |125| `$?` | Exit status of last command |126| `$$` | PID of the shell |127| `$!` | PID of last background command |128| `$-` | Current option flags |129| `$_` | Last argument of previous command |130131### Compound Commands132133> Full details: `shell-syntax-and-commands.md` (section 3)134135```bash136# If137if cmd; then ...; elif cmd; then ...; else ...; fi138139# For140for var in words; do ...; done141for (( init; test; step )); do ...; done142143# While / Until144while cmd; do ...; done145until cmd; do ...; done146147# Case148case word in149 pattern1|pattern2) commands ;; # break150 pattern3) commands ;& # fall-through151 pattern4) commands ;;& # test next152esac153154# Select (menu)155select var in words; do ...; done156157# Test158[[ expression ]] # Preferred (no word splitting/globbing)159(( expression )) # Arithmetic evaluation160161# Grouping162{ commands; } # Current shell (note: space after {, ; before })163( commands ) # Subshell164```165166### Test Operators (`[[ ]]` and `test`/`[ ]`)167168> Full details: `bash-features.md` (section 4)169170| Operator | Test |171|-----------------------|----------------------------------|172| `-e file` | Exists |173| `-f file` | Regular file |174| `-d file` | Directory |175| `-L file` / `-h file` | Symlink |176| `-s file` | Non-zero size |177| `-r file` | Readable |178| `-w file` | Writable |179| `-x file` | Executable |180| `-p file` | Named pipe |181| `-S file` | Socket |182| `-b file` | Block device |183| `-c file` | Character device |184| `-t fd` | FD is terminal |185| `-O file` | Owned by effective UID |186| `-G file` | Owned by effective GID |187| `-N file` | Modified since last read |188| `f1 -nt f2` | f1 newer than f2 |189| `f1 -ot f2` | f1 older than f2 |190| `f1 -ef f2` | Same inode |191| `-v var` | Variable is set |192| `-R var` | Variable is nameref |193| `-z string` | Zero length |194| `-n string` | Non-zero length |195| `s1 == s2` | Equal (pattern match in `[[ ]]`) |196| `s1 != s2` | Not equal |197| `s1 < s2` | Less than (lexicographic) |198| `s1 > s2` | Greater than (lexicographic) |199| `s1 =~ regex` | Regex match (`[[ ]]` only) |200| `n1 -eq n2` | Numeric equal |201| `n1 -ne n2` | Numeric not equal |202| `n1 -lt n2` | Numeric less than |203| `n1 -le n2` | Numeric less/equal |204| `n1 -gt n2` | Numeric greater than |205| `n1 -ge n2` | Numeric greater/equal |206207### Redirections208209> Full details: `redirections-and-execution.md` (section 1)210211| Syntax | Operation |212|--------------------------------------|------------------------------------|213| `cmd < file` | Stdin from file |214| `cmd > file` | Stdout to file (truncate) |215| `cmd >> file` | Stdout to file (append) |216| `cmd 2> file` | Stderr to file |217| `cmd &> file` or `cmd > file 2>&1` | Stdout+stderr to file |218| `cmd &>> file` or `cmd >> file 2>&1` | Stdout+stderr append |219| `cmd >| file` | Force overwrite (noclobber) |220| `cmd <<EOF` | Here document |221| `cmd <<-EOF` | Here document (strip leading tabs) |222| `cmd <<< "string"` | Here string |223| `cmd <&fd` | Duplicate input FD |224| `cmd >&fd` | Duplicate output FD |225| `cmd fd<&-` | Close input FD |226| `cmd fd>&-` | Close output FD |227| `cmd n<>file` | Open for read+write on FD n |228| `cmd {var}> file` | Auto-assign FD to var |229230Special filenames in redirections: `/dev/fd/N`, `/dev/stdin`, `/dev/stdout`, `/dev/stderr`, `/dev/tcp/host/port`, `/dev/udp/host/port`231232### Arrays233234> Full details: `bash-features.md` (section 6)235236```bash237# Indexed arrays238declare -a arr=(one two three)239arr[0]="value"240arr+=(more items)241242# Associative arrays (Bash 4.0+)243declare -A map=([key1]=val1 [key2]=val2)244map[key]="value"245246# Access247${arr[0]} # Single element248${arr[@]} # All elements (separate words)249${arr[*]} # All elements (single word with IFS)250${#arr[@]} # Number of elements251${!arr[@]} # All indices/keys252${arr[@]:off:len} # Slice253254# Unset255unset 'arr[2]' # Remove element (quote to prevent glob)256unset arr # Remove entire array257```258259### Expansion Order2602611. Brace expansion2622. Tilde expansion2633. Parameter and variable expansion2644. Arithmetic expansion2655. Command substitution (left-to-right)2666. Process substitution2677. Word splitting2688. Filename expansion (globbing)2699. Quote removal270271Steps 2-6 happen left-to-right simultaneously. Full details with word-count impacts: `functions-parameters-expansions.md` (section 3.5).272273### Common `set` Options274275> Full details: `shell-builtins.md` (section 2, `set` builtin)276277| Option | Effect |278|------------------------|------------------------------------------------|279| `set -e` (`errexit`) | Exit on error (with exceptions) |280| `set -u` (`nounset`) | Error on unset variables |281| `set -o pipefail` | Pipeline fails if any command fails |282| `set -x` (`xtrace`) | Print commands before execution |283| `set -f` (`noglob`) | Disable filename expansion |284| `set -n` (`noexec`) | Read commands without executing (syntax check) |285| `set -o posix` | POSIX compliance mode |286| `set -E` (`errtrace`) | ERR trap inherited by functions |287| `set -T` (`functrace`) | DEBUG/RETURN traps inherited by functions |288289### Essential `shopt` Options290291> Full details: `shell-builtins.md` (section 3, `shopt` options)292293| Option | Effect |294|---------------------|-----------------------------------------------------------------|295| `extglob` | Extended patterns: `?(pat)` `*(pat)` `+(pat)` `@(pat)` `!(pat)` |296| `globstar` | `**` matches directories recursively |297| `nullglob` | Unmatched globs expand to nothing |298| `failglob` | Unmatched globs cause error |299| `nocaseglob` | Case-insensitive globbing |300| `nocasematch` | Case-insensitive `case` and `[[ == ]]` |301| `dotglob` | Globs match dotfiles |302| `lastpipe` | Last pipeline command runs in current shell |303| `inherit_errexit` | Command substitutions inherit `errexit` |304| `assoc_expand_once` | Expand associative array subscripts once |305306### Trap Signals307308> Full details: `shell-builtins.md` (`trap` builtin) and `redirections-and-execution.md` (section 5, Signals)309310```bash311trap 'cleanup' EXIT # On shell exit312trap 'handle_err' ERR # On command error (with set -e)313trap 'on_debug' DEBUG # Before every command314trap 'on_return' RETURN # After function/sourced script returns315trap 'handle_int' INT # Ctrl-C316trap 'handle_term' TERM # kill signal317trap '' SIGNAL # Ignore signal318trap - SIGNAL # Reset to default319```320321### Arithmetic Operators (inside `(( ))` and `$(( ))`)322323> Full details: `bash-features.md` (section 5)324325All C-style operators: `+`, `-`, `*`, `/`, `%`, `**` (exponent), `<<`, `>>`, `&`, `|`, `^`, `~`, `!`, `&&`, `||`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `<<=`, `>>=`, `&=`, `|=`, `^=`, `++`, `--`, `expr?expr:expr` (ternary), `expr,expr` (comma)326327Bases: `0x` (hex), `0` (octal), `0b` (binary), `base#number` (arbitrary base 2-64)328329### Prompt Escape Sequences330331> Full details: `bash-features.md` (section 8, Controlling the Prompt)332333| Escape | Meaning |334|-----------|-------------------------------|335| `\u` | Username |336| `\h` | Hostname (short) |337| `\H` | Hostname (full) |338| `\w` | Working directory |339| `\W` | Basename of working directory |340| `\d` | Date (Day Mon Date) |341| `\t` | Time (HH:MM:SS 24hr) |342| `\T` | Time (HH:MM:SS 12hr) |343| `\@` | Time (AM/PM) |344| `\A` | Time (HH:MM 24hr) |345| `\D{fmt}` | strftime format |346| `\j` | Number of jobs |347| `\!` | History number |348| `\#` | Command number |349| `\$` | `#` if root, `$` otherwise |350| `\[` | Begin non-printing chars |351| `\]` | End non-printing chars |352353## Definitions354355| Term | Definition |356|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|357| **blank** | Space or tab |358| **word** | Sequence of characters treated as a unit (no unquoted metacharacters) |359| **token** | A word or an operator |360| **metacharacter** | Unquoted: space, tab, newline, `\|`, `&`, `;`, `(`, `)`, `<`, `>` |361| **control operator** | `\|\|`, `&&`, `&`, `;`, `;;`, `;&`, `;;&`, `\|`, `\|&`, `(`, `)`, newline |362| **name/identifier** | Letters, numbers, underscores; starts with letter or underscore |363| **exit status** | 0-255; 0 = success, 1 = general error, 2 = usage error, 126 = not executable, 127 = not found, 128+N = killed by signal N |364| **special builtin** | POSIX-designated builtins that have special properties (break, :, ., continue, eval, exec, exit, export, readonly, return, set, shift, trap, unset) |365366## Common Patterns367368### Safe Script Header369```bash370#!/usr/bin/env bash371set -euo pipefail372```373374### Temporary Files375```bash376tmpfile=$(mktemp) || exit 1377trap 'rm -f "$tmpfile"' EXIT378```379380### Read File Line by Line381```bash382while IFS= read -r line; do383 printf '%s\n' "$line"384done < "$file"385```386387### Default Values388```bash389name="${1:-default}" # Use default if $1 unset/empty390name="${1:?'missing arg'}" # Exit with error if $1 unset/empty391```392393### String Operations394```bash395# Lowercase / Uppercase396lower="${str,,}"397upper="${str^^}"398first_cap="${str^}"399400# Trim prefix/suffix401filename="${path##*/}" # basename402dir="${path%/*}" # dirname403ext="${file##*.}" # extension404noext="${file%.*}" # remove extension405```406407### Array Iteration408```bash409for item in "${arr[@]}"; do echo "$item"; done # values410for i in "${!arr[@]}"; do echo "$i: ${arr[$i]}"; done # index: value411```412413### Process Substitution414```bash415diff <(sort file1) <(sort file2)416while IFS= read -r line; do ...; done < <(cmd) # avoid subshell417```418419### Associative Array Check420```bash421declare -A map422if [[ -v map["key"] ]]; then echo "exists"; fi423```424425## Common Mistakes426427### Unquoted variables (word splitting + globbing)428429```bash430# BAD: word splits and globs if file contains spaces or wildcards431for f in $files; do rm $f; done432433# GOOD: always quote variable expansions434for f in "${files[@]}"; do rm "$f"; done435```436437### `[ ]` vs `[[ ]]`438439```bash440# BAD: word splitting inside [ ] can break with spaces in $var441[ $var == "hello" ] # also: == is not POSIX in [ ]442443# GOOD: [[ ]] prevents word splitting and supports == and =~444[[ $var == "hello" ]]445```446447### `$@` vs `$*` quoting448449```bash450# BAD: loses word boundaries451for arg in $@; do echo "$arg"; done452453# GOOD: preserves each argument as a separate word454for arg in "$@"; do echo "$arg"; done455456# "$*" joins all args into ONE word (separated by first char of IFS)457```458459### `set -e` doesn't trigger everywhere460461```bash462set -e463# These do NOT cause exit on failure:464if false; then :; fi # test in 'if'465false || true # LHS of ||466false && true # LHS of &&467false | true # pipeline (without pipefail)468! false # negated command469```470471### Missing `;` before `}` in brace groups472473```bash474# BAD: syntax error475{ echo "hello" }476477# GOOD: semicolon (or newline) required before }478{ echo "hello"; }479```480481### Array access without braces482483```bash484arr=(one two three)485486# BAD: expands $arr (element 0) then appends literal [1]487echo $arr[1] # prints: one[1]488489# GOOD: braces required for array subscript490echo "${arr[1]}" # prints: two491```492493### Forgetting `declare -A` for associative arrays494495```bash496# BAD: creates an indexed array, keys treated as arithmetic (0)497map=([foo]=1 [bar]=2)498echo "${map[foo]}" # prints: 2 (both keys evaluated to index 0)499500# GOOD: must declare associative arrays explicitly501declare -A map=([foo]=1 [bar]=2)502echo "${map[foo]}" # prints: 1503```504505### Using `=` vs `==` in the wrong context506507```bash508# In [ ] / test: use = (POSIX). == works in Bash but is not portable.509[ "$a" = "$b" ]510511# In [[ ]]: both = and == work; RHS is a pattern (quote for literal match)512[[ "$a" == "$b" ]] # literal match (RHS quoted)513[[ "$a" == "$b"* ]] # glob pattern (unquoted * appended)514[[ "$a" == $b ]] # if $b contains *, it's a pattern (RHS unquoted)515```516517### Subshell variable loss in pipes518519```bash520# BAD: read runs in subshell, $var is lost after pipeline521echo "hello" | read var522echo "$var" # empty523524# GOOD: use process substitution or lastpipe525read var < <(echo "hello")526echo "$var" # hello527528# OR: enable lastpipe (non-interactive, no job control)529shopt -s lastpipe530echo "hello" | read var531```532533### `local` variables use dynamic scoping534535```bash536inner() { echo "$x"; }537outer() { local x=42; inner; }538outer # prints: 42 (inner sees outer's local!)539540# This is dynamic scoping, not lexical. Any function called541# from a scope with a local variable sees that variable.542```543544### Here-strings always append a trailing newline545546```bash547read -r var <<< "hello"548printf '%s' "$var" | xxd # contains "hello\n" — trailing newline added549# Use printf instead when exact bytes matter:550read -r var < <(printf '%s' "hello")551```552553### `declare -i` silently evaluates strings as arithmetic554555```bash556declare -i num557num="1+1"558echo "$num" # prints: 2 (string was evaluated!)559# WARNING: with untrusted input this is a code injection vector:560# declare -i x; x="a]$(cmd)" would execute cmd561```562563### `trap EXIT` is reset in subshells564565```bash566trap 'echo cleanup' EXIT567(echo "subshell") # EXIT trap does NOT fire here568# Subshells inherit the parent's traps but reset EXIT/ERR/DEBUG/RETURN.569# If you need cleanup in a subshell, set a new trap inside it.570```571572---573> Converted and distributed by [TomeVault](https://tomevault.io/claim/bitranox) — claim your Tome and manage your conversions.574<!-- tomevault:4.0:skill_md:2026-04-14 -->