Parameter Expansion

String manipulation without external tools — path extraction, default values, substitution, case conversion. Pure bash, no fork overhead.

Parameter Expansion

String manipulation without calling external tools — pure bash, no fork.

Path Manipulation

Extract basename and dirname without external commands
var="docs/modules/ROOT/pages/codex/bash/safe-workflows.adoc"

echo "${var##*/}"     # safe-workflows.adoc   (basename — strip longest prefix up to /)
echo "${var%/*}"      # docs/modules/ROOT/pages/codex/bash  (dirname — strip shortest suffix from /)
echo "${var##*.}"     # adoc  (extension — strip longest prefix up to .)
echo "${var%.*}"      # docs/modules/ROOT/pages/codex/bash/safe-workflows  (strip extension)
Mnemonic: # strips from left, % strips from right
# Single # or % — shortest match (greedy from the boundary)
# Double ## or %% — longest match (greedy through the string)

file="backup.2026.04.10.tar.gz"
echo "${file#*.}"     # 2026.04.10.tar.gz  (shortest — first dot)
echo "${file##*.}"    # gz                  (longest — last dot)
echo "${file%.*}"     # backup.2026.04.10.tar  (shortest from right)
echo "${file%%.*}"    # backup              (longest from right)

Defaults and Guards

Default value if unset
echo "${EDITOR:-vim}"         # uses vim if EDITOR is unset or empty
echo "${EDITOR-vim}"          # uses vim if EDITOR is unset (empty string is kept)
Assign default if unset
: "${TMPDIR:=/tmp}"           # sets TMPDIR to /tmp if unset
# : is a no-op — prevents the expansion from being executed as a command
Error if unset
: "${API_TOKEN:?API_TOKEN must be set}"
# Exits with error message if API_TOKEN is unset or empty

Substitution

Replace first occurrence
path="codex/cli/grep.adoc"
echo "${path/cli/grep}"       # codex/grep/grep.adoc
Replace all occurrences
dashed="port-smtp-submission"
echo "${dashed//-/_}"         # port_smtp_submission
Case conversion (bash 4+)
name="evan"
echo "${name^}"               # Evan     (capitalize first)
echo "${name^^}"              # EVAN     (all upper)

LOUD="HELLO"
echo "${LOUD,}"               # hELLO   (lowercase first)
echo "${LOUD,,}"              # hello    (all lower)

Length and Substring

String length
str="hello"
echo "${#str}"                # 5
Substring extraction
str="hello world"
echo "${str:6}"               # world    (from position 6)
echo "${str:0:5}"             # hello    (from 0, length 5)

See Also

  • Variables — basic variable assignment and quoting

  • Tests — string comparison operators