Bash Scripting

Bash (Bourne Again SHell) is the default shell on most Linux distributions and the lingua franca of system administration, penetration testing, and automation. Its parameter expansion and text-processing capabilities make it a powerful tool for parsing, enumeration, and one-liner payloads. 1

Brace expansion

{X,Y}      # → X Y
{X,Y}.txt  # → X.txt Y.txt
{1..10}    # → 1 2 3 4 5 6 7 8 9 10
{1..10..2} # → 1 3 5 7 9

Brace expansion happens before parameter expansion, making it useful for generating lists of filenames, IPs, or ports without external tools.

Special variables

VariableMeaning
$#Number of positional arguments
$1$9Positional arguments (no $10 and higher without ${10})
"$@"All arguments as separate quoted strings
"$*"All arguments as a single string, joined by first IFS character
IFSInternal Field Separator — delimiter characters for word splitting (default: <space><tab><newline>)

Parameter expansion

MYVAR=/path/to/file/file.tar.gz
 
${#MYVAR}              # 25 (length)
 
# Suffix removal
${MYVAR%.*}            # /path/to/file/file.tar
${MYVAR%%.*}           # /path/to/file/file
 
# Prefix removal
${MYVAR#*/}            # path/to/file/file.tar.gz
${MYVAR##*/}           # file.tar.gz
 
# Substitution
${MYVAR/file/newfile}  # /path/to/newfile/file.tar.gz
${MYVAR//file/newfile} # /path/to/newfile/newfile.tar.gz
 
# Substring extraction
${MYVAR:1:4}           # path
${MYVAR:(-6):3}        # tar

Default values

${MYVAR:-default}  # Return $MYVAR, or "default" if unset/empty
${MYVAR:=default}  # Set $MYVAR to "default" if unset/empty, then return it
${MYVAR:+default}  # Return "default" if $MYVAR is set (otherwise empty)
${MYVAR:?error}    # Exit with "error" if $MYVAR is unset/empty

Indirect references (“variable variables”)

VAR1="Hello world"
VAR2="VAR1"
${!VAR2}  # Hello world

Arrays

MYARRAY=("element0" "element1" "element2")
MYARRAY[3]="element3"
 
${MYARRAY[0]}      # element0
${MYARRAY[-1]}     # element3 (negative index from end)
${MYARRAY[@]}      # all elements
${MYARRAY[@]:1:2}  # element1 element2 (slice)
${!MYARRAY[@]}     # 0 1 2 3 (indices)
${#MYARRAY[@]}     # 4 (array size)
 
unset MYARRAY[3]   # remove element by index

Associative arrays (dictionaries)

declare -A MYDICT
MYDICT[key]="value"
${MYDICT[key]}     # value
${!MYDICT[@]}      # all keys
${#MYDICT[@]}      # number of entries

Arithmetic

$(( 1 + 2 ))  # 3
$RANDOM       # random-ish integer (0–32767)

Looping over lines

# Simple — creates a subshell (variables set inside don't persist)
cat $FILE | while read -r LINE; do
    # do stuff with $LINE
done
 
# Process substitution — no subshell, variables persist
while IFS= read -d '' -r FILE; do
    # do stuff with $FILE
done < <(find $DIR -type f -print0)

The read -d '' form reads null-delimited input (from find -print0), handling filenames with spaces and newlines correctly. The space between -d and '' is required — Bash interprets the empty string as the null character.

Sources

Related: linux-reconnaissance-commands, shell-stabilization, python, remove-duplicate-lines-bash, read-dash-file, unbuffer, tmux, basenc-base64-url-safe-encoding

Footnotes

  1. GNU Bash Reference Manual