Complete Guide to Bash Special Syntax, Variables, and Expansions
Overview
Section titled “Overview”This article provides a comprehensive summary of all special syntax, variables, expansion rules, and control structures used in Bash shell scripting.
Variable Notation
Section titled “Variable Notation”Dynamic or environment-dependent values are denoted as <<variable>>.
All examples below explicitly show their usage.
| Variable | Example | Description |
|---|---|---|
<<var>> | name, path, user | Arbitrary variable name |
<<default>> | guest, 8080 | Default or fallback value |
<<pattern>> | *.txt, */ | File or string pattern |
<<offset>> | 0, 3 | Starting index of substring (0-based) |
<<length>> | 4, 10 | Length of substring |
<<prefix>> | ENV_, HOST | Prefix pattern for variable names |
<<index>> | 0, 1, 2 | Array or associative key index |
<<file>> | /tmp/test.txt | File path |
Step 1: Metacharacters
Section titled “Step 1: Metacharacters”| Symbol | Meaning | Example |
|---|---|---|
* | Matches any string | ls *.txt → lists all .txt files |
? | Matches any single character | ls ?.sh → matches a.sh, b.sh |
[a-z] | Range match | ls [A-Z]* → files starting with uppercase |
{a,b} | Brace expansion | mv {hoge,huga} |
{1..3} | Sequence expansion | touch file{1..3}.txt |
$ | Variable expansion | echo $HOME |
! (negation) | Logical NOT | [[ ! -f test.txt ]] |
! (history) | History expansion | !10 → reruns command #10 |
~ | Home directory | cd ~ |
; | Command separator | pwd; ls |
&& | Execute if previous succeeded | make && echo OK |
| ` | ` | |
& | Run in background | sleep 5 & |
| ` | ` | Pipe output |
> | Redirect stdout | echo hi > out.txt |
>> | Append output | echo hi >> out.txt |
< | Redirect stdin | wc -l < file.txt |
() | Subshell | (cd /tmp; ls) |
{} | Same shell block | { echo A; echo B; } |
\ | Escape character | echo \$HOME |
' ' | Literal (no expansion) | echo '$USER' |
" " | Expand variables | echo "$USER" |
Step 2: Special Variables
Section titled “Step 2: Special Variables”| Variable | Description | Example |
|---|---|---|
$0 | Script name | echo $0 → script.sh |
$1–$9 | Positional args | echo $1 |
$@ | All args as array | for a in "$@"; do echo $a; done |
$# | Arg count | echo $# |
$? | Last exit status | ls /nope; echo $? |
$$ | Current PID | echo $$ |
$! | Last BG job PID | sleep 10 & echo $! |
$- | Current shell options | echo $- |
$_ | Last arg of previous cmd | echo $_ |
$PPID | Parent PID | echo $PPID |
$RANDOM | Random number | echo $RANDOM |
$SECONDS | Seconds since shell start | echo $SECONDS |
$FUNCNAME | Function name | f(){ echo $FUNCNAME; }; f |
$PIPESTATUS[@] | Exit status of pipe cmds | `ls |
Step 3: Parameter Expansion
Section titled “Step 3: Parameter Expansion”| Syntax | Description | Example |
|---|---|---|
${<<var>>} | Variable expansion | name=user; echo ${name} |
${<<var>>:-<<default>>} | Use default if unset | echo ${user:-guest} |
${<<var>>:=<<default>>} | Assign default if unset | echo ${port:=8080} |
${<<var>>:+alt} | Use alt if set | x=1; echo ${x:+OK} |
${<<var>>:?msg} | Error if unset | echo ${config:?missing} |
${#<<var>>} | String length | name=user; echo ${#name} |
${<<var>>%<<pattern>>} | Remove shortest suffix | path=/a/b/c; echo ${path%/*} |
${<<var>>%%<<pattern>>} | Remove longest suffix | echo ${path%%/*} |
${<<var>>#<<pattern>>} | Remove shortest prefix | echo ${path#*/} |
${<<var>>##<<pattern>>} | Remove longest prefix | echo ${path##*/} |
${<<var>>/<<pattern>>/<<repl>>} | Replace first match | echo ${msg/foo/bar} |
${<<var>>//<<pattern>>/<<repl>>} | Replace all | echo ${msg// /_} |
${<<var>>:<<offset>>} | Substring from offset | s=abcdef; echo ${s:2} |
${<<var>>:<<offset>>:<<length>>} | Substring with length | echo ${s:1:3} |
${!<<prefix>>*} | Vars with prefix | HOST1=x; HOST2=y; echo ${!HOST*} |
${!<<var>>} | Indirect reference | ref=NAME; NAME=user; echo ${!ref} |
${<<var>>,} / ${<<var>>^^} | Case conversion | n=abc; echo ${n^^} |
${<<var>>@Q} | Quoted form | x='abc'; echo ${x@Q} |
Step 4: Arrays and Associative Arrays
Section titled “Step 4: Arrays and Associative Arrays”arr=(a b c)echo ${arr[<<index>>]} # Access elementecho ${#arr[@]} # Countfor i in "${arr[@]}"; do echo $i; done
declare -A mapmap[<<index>>]=100map[name]=userecho ${map[<<index>>]} # Valueecho ${!map[@]} # KeysStep 5: Arithmetic Expansion
Section titled “Step 5: Arithmetic Expansion”x=5; y=3echo $((x + y)) # 8((x *= 2))echo $x # 10Step 6: Conditions and Comparisons
Section titled “Step 6: Conditions and Comparisons”if [ "$USER" = "root" ]; then echo root; fiif [ "$x" -lt 10 ]; then echo small; fiif [ -f /etc/passwd ]; then echo exists; fis="hello123"[[ $s =~ [0-9]+ ]] && echo "has number"Step 7: Command Substitution and Subshells
Section titled “Step 7: Command Substitution and Subshells”echo "Today: $(date +%Y-%m-%d)"(cd /tmp; ls)Step 8: Redirection and File Descriptors
Section titled “Step 8: Redirection and File Descriptors”echo "Hello" > <<file>>echo "Append" >> <<file>>wc -l < <<file>>ls /nope 2> err.logecho "Error" >&2exec 3> custom.logecho "via fd3" >&3exec 3>&-File Descriptor Reference
Section titled “File Descriptor Reference”| FD | Name | Description | Example |
|---|---|---|---|
0 | stdin | Input | < file.txt |
1 | stdout | Normal output | echo test > out.txt |
2 | stderr | Error output | ls /nope 2> err.log |
3+ | Custom | User-defined streams | exec 3> log.txt |
FD3 is a custom descriptor:
exec 3> process.logecho "start" >&3exec 3>&-Step 9: Traps and Error Handling
Section titled “Step 9: Traps and Error Handling”set -eset -uset -xset -o pipefail
trap 'echo done' EXITtrap 'echo error' ERRStep 10: Job Control
Section titled “Step 10: Job Control”sleep 10 &jobsfg %1bg %1disown %1kill %1Job Reference (%1)
Section titled “Job Reference (%1)”Example:
sleep 60 &jobsOutput:
[1]+ Running sleep 60 &| Symbol | Meaning |
|---|---|
%1 | Job ID 1 |
%+ | Current job |
%- | Previous job |
Step 11: Reserved Commands
Section titled “Step 11: Reserved Commands”: # No-optruefalsesource ~/.bashrceval "echo executed"{ echo A; echo B; }Summary
Section titled “Summary”This guide comprehensively covered Bash’s special syntax, expansions, variables, metacharacters, and control structures.
Understanding these concepts enables you to write safe, reusable, and automation-ready shell scripts.