Bash Parameter Expansion

Parameter expansion reshapes a variable value while Bash reads it. It sets defaults, trims text, replaces words, and measures length without calling outside tools. The syntax uses curly braces: ${variable} with a special symbol inside.

Picture the Idea

  file="report_final.txt"

  ${file}          --> report_final.txt     (plain value)
  ${#file}         --> 16                   (length)
  ${file%.txt}     --> report_final         (cut the ending)
  ${file/final/v2} --> report_v2.txt        (swap a word)

Default Values

FormResult
${name:-Guest}Use Guest when name is empty or unset
${name:=Guest}Use Guest and also store it in name
${name:+Member}Use Member only when name has a value
${name:?Missing}Stop with an error message when name is empty
#!/bin/bash
user=${1:-Guest}
echo "Welcome, $user"

Running the script with no argument prints Welcome, Guest.

String Length

word="Bash"
echo ${#word}

The output is 4.

Cut a Piece of Text

The form ${variable:start:length} counts from zero.

text="Hello World"
echo ${text:0:5}    # Hello
echo ${text:6}      # World
echo ${text: -5}    # World (count from the end)

Remove a Pattern From the Start or End

The hash symbol trims the beginning. The percent symbol trims the end. One symbol removes the shortest match, and two symbols remove the longest match.

path="/home/asha/photo.tar.gz"

echo ${path%.gz}       # /home/asha/photo.tar
echo ${path%%.*}       # /home/asha/photo
echo ${path#*/}        # home/asha/photo.tar.gz
echo ${path##*/}       # photo.tar.gz

The last line mimics the basename command and returns only the file name.

Replace Text

sentence="red apple, red cherry"
echo ${sentence/red/green}     # green apple, red cherry
echo ${sentence//red/green}    # green apple, green cherry

One slash replaces the first match. Two slashes replace every match.

Change Letter Case

Bash 4 or higher supports case conversion:

name="asha sharma"
echo ${name^}     # Asha sharma
echo ${name^^}    # ASHA SHARMA
word="BASH"
echo ${word,,}    # bash

Practical Example: Rename Many Files

This script changes every .txt file to .md:

#!/bin/bash
for file in *.txt
do
  mv "$file" "${file%.txt}.md"
done

The expression ${file%.txt} removes the old ending, and the script adds the new one.

Practical Example: Split a Path

#!/bin/bash
full="/var/log/app/server.log"
name=${full##*/}
folder=${full%/*}
echo "Name: $name"
echo "Folder: $folder"

Output:

Name: server.log
Folder: /var/log/app

Indirect Reference

An exclamation mark reads a variable whose name sits inside another variable:

color="red"
red="#FF0000"
echo ${!color}

The output is #FF0000.

Practical Example: Safe Folder Variable

A missing variable can turn a delete command into a disaster. The error form of expansion stops the script before harm happens.

#!/bin/bash
backup_dir=${BACKUP_DIR:?Set BACKUP_DIR before running}
echo "Cleaning $backup_dir"
rm -f "$backup_dir"/*.tmp

The script prints the message and exits when BACKUP_DIR is empty. Without the check, the path would shrink to /*.tmp and touch files at the top of the system.

Expansion Compared With External Tools

TaskExternal ToolExpansion
Get file namebasename "$path"${path##*/}
Get folderdirname "$path"${path%/*}
Count charactersecho "$s" | wc -c${#s}
Uppercase textecho "$s" | tr a-z A-Z${s^^}

Expansion avoids starting a new process, so loops with thousands of lines finish much faster.

Key Takeaways

  • ${var:-default} supplies a fallback value.
  • ${#var} returns the length.
  • ${var:start:length} extracts part of a string.
  • # trims from the front and % trims from the back.
  • ${var/old/new} replaces text, and a double slash replaces all matches.
  • Expansion runs inside Bash, so it is faster than calling sed or cut in a loop.