Bash Reference
A practical reference for Bash scripts, parameters, expansions, conditions, arrays, redirections, and builtins.
Updated 2026-07-22
Overview
Bash is both an interactive command interpreter and a programming language. It implements shell features defined by POSIX and adds arrays, extended tests, brace expansion, process substitution, job control, and other extensions.
Bash is not the same language as every shell. A script that uses [[ ]], arrays, brace expansion, or process substitution should explicitly run with Bash instead of assuming /bin/sh provides those features.
#!/usr/bin/env bash
name=${1:-World}
printf 'Hello, %s\n' "$name" Invocation and Scripts
| Command | Meaning |
|---|---|
| bash | Start an interactive Bash shell |
| bash script.sh | Read and execute commands from a file |
| bash -c 'commands' | Execute commands supplied as an argument |
| bash -n script.sh | Read commands and check syntax without executing them |
| bash -x script.sh | Print expanded commands while executing |
| bash --version | Display Bash version information |
| source file | Execute a file in the current shell environment |
| exec command | Replace the current shell process with command |
Quoting
| Form | Behavior |
|---|---|
| \character | Preserve the literal value of the next character |
| 'text' | Preserve every character literally; a single quote cannot occur inside |
| "text" | Allow parameter, command, and arithmetic expansion while suppressing word splitting and pathname expansion |
| $'text' | Interpret backslash escapes such as \n and \t |
| $"text" | Mark a string for locale translation |
Variables and Parameters
| Syntax | Meaning |
|---|---|
| name=value | Assign a shell variable |
| export name | Include a variable in environments of subsequently executed commands |
| readonly name | Prevent reassignment or removal |
| local name=value | Create a variable local to the current function |
| declare -i count=0 | Declare a variable with the integer attribute |
| unset name | Remove a variable or function |
| ${name} | Expand a parameter |
| ${name:-word} | Use word when name is unset or empty |
| ${name:=word} | Assign and use word when name is unset or empty |
| ${name:?message} | Write an error when name is unset or empty |
| ${name:+word} | Use word when name is set and nonempty |
| ${#name} | String length |
| ${name:offset:length} | Substring expansion |
| ${name#pattern} | Remove shortest matching prefix |
| ${name##pattern} | Remove longest matching prefix |
| ${name%pattern} | Remove shortest matching suffix |
| ${name%%pattern} | Remove longest matching suffix |
| ${name/pattern/replacement} | Replace the first matching pattern |
| Special parameter | Meaning |
|---|---|
| $0 | Shell or script name |
| $1 … $9 | Positional parameters |
| ${10} | Positional parameters above 9 require braces |
| $# | Number of positional parameters |
| "$@" | Each positional parameter as a separate word |
| "$*" | All positional parameters joined into one word |
| $? | Status of the most recent foreground pipeline |
| $$ | Process ID of the shell |
| $! | Process ID of the most recent asynchronous command |
| $- | Current shell option flags |
Shell Expansions
Bash performs expansions in a defined sequence. Brace expansion occurs first, followed by tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, and process substitution. Word splitting and pathname expansion follow, and quote removal occurs last.
| Syntax | Expansion |
|---|---|
| {one,two} | Brace expansion |
| {1..5} | Sequence expression |
| ~ or ~user | Home-directory expansion |
| $name or ${name} | Parameter expansion |
| $(( expression )) | Arithmetic expansion |
| $(command) | Command substitution |
| <(command) | Process substitution supplying a readable filename |
| >(command) | Process substitution supplying a writable filename |
| *.txt | Pathname expansion using a glob pattern |
Conditions and Tests
| Expression | True when |
|---|---|
| [[ -e $path ]] | Path exists |
| [[ -f $path ]] | Path is a regular file |
| [[ -d $path ]] | Path is a directory |
| [[ -r $path ]] | Path is readable |
| [[ -w $path ]] | Path is writable |
| [[ -x $path ]] | Path is executable |
| [[ -n $value ]] | String has nonzero length |
| [[ -z $value ]] | String has zero length |
| [[ $left == $right ]] | Strings are equal |
| [[ $value == pattern ]] | Value matches a shell pattern when pattern is unquoted |
| [[ $value =~ regex ]] | Value matches an extended regular expression |
| (( left < right )) | Arithmetic comparison is true |
| command | Command exits with status 0 |
if [[ -f $path && -r $path ]]; then
printf 'Readable file: %s\n' "$path"
elif [[ -e $path ]]; then
printf 'The path exists but is not a readable file\n'
else
printf 'The path does not exist\n' >&2
fi Control Flow and Functions
for file in "$@"; do
printf '%s\n' "$file"
done
while read -r line; do
printf 'Line: %s\n' "$line"
done < input.txt
case $answer in
[Yy]|[Yy][Ee][Ss]) printf 'yes\n' ;;
[Nn]|[Nn][Oo]) printf 'no\n' ;;
*) printf 'unknown\n' ;;
esac greet() {
local name=${1:?name is required}
printf 'Hello, %s\n' "$name"
}
greet Ada Arrays
items=("first value" second third)
printf 'First: %s\n' "${items[0]}"
printf 'Count: %d\n' "${#items[@]}"
for item in "${items[@]}"; do
printf 'Item: %s\n' "$item"
done
declare -A colors=([error]=red [success]=green)
printf '%s\n' "${colors[success]}" | Syntax | Meaning |
|---|---|
| ${array[index]} | One indexed element |
| "${array[@]}" | Every element as a separate word |
| ${#array[@]} | Number of elements |
| ${!array[@]} | All assigned indexes or keys |
| array+=(value) | Append an indexed element |
| unset 'array[index]' | Remove an element |
| declare -a array | Declare an indexed array |
| declare -A map | Declare an associative array |
Redirections and Pipelines
| Syntax | Meaning |
|---|---|
| command > file | Redirect standard output and truncate file |
| command >> file | Append standard output |
| command < file | Read standard input from file |
| command 2> file | Redirect standard error |
| command > file 2>&1 | Redirect output, then duplicate standard error to it |
| command &> file | Bash shorthand for redirecting output and error |
| left | right | Connect left standard output to right standard input |
| left |& right | Pipe both output and error from left |
| command <<< "$text" | Supply a here string as standard input |
| command <<EOF | Supply a here document |
| command <<'EOF' | Supply a here document without expanding its body |
| exec 3> file | Open file descriptor 3 for writing |
| exec 3>&- | Close file descriptor 3 |
Common Builtins
| Builtin | Purpose |
|---|---|
| alias / unalias | Define or remove interactive command aliases |
| builtin | Run a shell builtin explicitly |
| cd / pwd | Change or display the working directory |
| command | Run a command while bypassing shell functions with the same name |
| declare / typeset | Set variables and their attributes |
| echo | Write arguments; printf is preferable when formatting matters |
| enable | Enable or disable shell builtins |
| help | Display help for Bash builtins |
| mapfile / readarray | Read lines into an indexed array |
| printf | Write formatted output |
| read | Read a line and split it into variables |
| shift | Remove leading positional parameters |
| source / . | Execute commands in the current shell |
| type | Describe how a command name would be interpreted |
| wait | Wait for processes or jobs and return their statuses |
help printf
type -a printf
command -V sed Options, Traps, and Debugging
| Syntax | Effect |
|---|---|
| set -u | Report an error when expanding an unset parameter |
| set -o pipefail | Use the rightmost nonzero status from a failed pipeline |
| set -x / set +x | Enable or disable execution tracing |
| set -e | Exit in some contexts when a command fails; behavior has important exceptions |
| shopt -s nullglob | Remove unmatched pathname patterns instead of leaving them literal |
| shopt -s globstar | Let ** match recursively in pathname expansion |
| trap handler EXIT | Run a handler when the shell exits |
| trap handler INT TERM | Run a handler for selected signals |
| trap - SIGNAL | Restore the original disposition of a signal |
temporary_directory=$(mktemp -d)
cleanup() {
rm -rf -- "$temporary_directory"
}
trap cleanup EXIT Interactive Use and Job Control
| Command or key | Effect |
|---|---|
| command & | Run a pipeline asynchronously |
| jobs | List jobs known to the current shell |
| fg %1 / bg %1 | Resume job 1 in the foreground or background |
| disown %1 | Remove job 1 from the shell’s job table |
| Ctrl-C | Interrupt the foreground job |
| Ctrl-Z | Suspend the foreground job |
| Ctrl-R | Search history backward |
| Ctrl-A / Ctrl-E | Move to the beginning or end of the line |
| Meta-B / Meta-F | Move backward or forward one word |