Skip to content
C.W.K.
Stream
Lesson 02 of 05 · published

Parameter Expansion Advanced

~13 min · parameter-expansion, default, substitute

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The expansion forms you'll use forever

Bash and zsh share a rich parameter-expansion language. Once these patterns are in your fingers, you stop reaching for sed for half of the tiny manipulations.

Defaults

  • ${var:-default} — value of var, or default if unset/empty.
  • ${var:=default} — same, but also assign the default.
  • ${var:+alt} — alt if var is set, else empty. Inverse.
  • ${var:?error} — exit with error if unset/empty. Great for required env vars.

Length

${#var}                    # string length
${#arr[@]}                 # array length

Substring

${var:5}                  # from char 5 to end
${var:5:3}                # 3 chars starting at 5
${var: -4}                # last 4 chars (note the space!)

Trim from front

  • ${var#prefix} — strip shortest match of prefix glob.
  • ${var##prefix} — strip longest.
path=/usr/local/bin
echo ${path#*/}            # usr/local/bin
echo ${path##*/}           # bin             (basename!)

Trim from back

  • ${var%suffix} — strip shortest match of suffix.
  • ${var%%suffix} — strip longest.
file=foo.tar.gz
echo ${file%.gz}           # foo.tar
echo ${file%%.*}           # foo

Substitution

  • ${var/from/to} — first match.
  • ${var//from/to} — every match.
  • ${var/#from/to} — only at the start.
  • ${var/%from/to} — only at the end.

Case

${var^^}                  # uppercase (bash 4+)
${var,,}                  # lowercase
${var^}                   # capitalize first letter

Why learn the forms

Parameter expansion avoids an external process and keeps small pathname or default-value operations local to the shell. Prefer it when the pattern is readable and the target shell supports it; use a dedicated text tool when records, encodings, or complex transformations make the contract clearer.

Patterns still have edge cases

The trim and substitution operands are shell patterns, and unquoted results can be split or expanded again. Quote expansions, test empty values and leading dots, and do not treat one expression as an exact replacement for every dirname or basename case.

Colon defaults and trim patterns are separate contracts

In forms such as ${var-default} and ${var:-default}, the colon decides whether an empty value counts like an unset one. In #, ##, %, and %% forms, the operand is a shell pattern rather than a literal substring. Test empty values and pattern characters explicitly.

Code

Real-life one-liners·bash
file=/path/to/document.tar.gz
echo "${file##*/}"      # document.tar.gz   (basename)
echo "${file%/*}"       # /path/to          (dirname)
echo "${file%.gz}"      # /path/to/document.tar
echo "${file%%.*}"      # /path/to/document
name=alice
echo "${name^^}"       # ALICE

External links

Exercise

Set path=/Users/me/notes/idea.md. Run all five expansions: ${path##*/}, ${path%/*}, ${path%.md}, ${path//\//-}, ${#path}. Memorize the three you use most — usually basename, dirname, suffix-strip.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.