Bash Command Substitution

Command substitution runs a command and places its output inside another command or variable. A script uses it to capture the date, a file count, a username, or any other live result.

The Idea in Plain Words

Imagine writing a note that says "Today's date is ___". A helper fills the blank with the real date before you read the note. Command substitution plays the role of that helper.

  echo "Today is $(date +%d-%m-%Y)"
                  |
                  v
          Bash runs: date +%d-%m-%Y
                  |
                  v
          Result:   16-10-2026
                  |
                  v
  echo "Today is 16-10-2026"

Two Syntax Styles

Modern Style: $( )

today=$(date +%A)
echo "It is $today"

Old Style: Backticks

today=`date +%A`
echo "It is $today"

Both styles give the same result. The $( ) style reads more clearly and allows nesting, so most writers prefer it.

Store Output in a Variable

#!/bin/bash
user_name=$(whoami)
folder=$(pwd)
echo "User: $user_name"
echo "Folder: $folder"

Output:

User: asha
Folder: /home/asha/scripts

Count Items

Combine a command with wc to count files:

count=$(ls | wc -l)
echo "This folder holds $count items"

Create Dated File Names

Backup scripts often attach the date to a file name:

#!/bin/bash
stamp=$(date +%Y%m%d_%H%M)
cp notes.txt "notes_backup_$stamp.txt"
echo "Created notes_backup_$stamp.txt"

Output:

Created notes_backup_20261016_1430.txt

Nested Substitution

A substitution can live inside another one:

echo "Folder name: $(basename $(pwd))"

Bash runs the inner pwd first and passes its result to basename. The final output holds only the last part of the path, such as scripts.

Use Substitution Inside Conditions

#!/bin/bash
if [ "$(whoami)" = "root" ]; then
  echo "Running with administrator rights"
else
  echo "Running as a normal user"
fi

Use Substitution in a Loop

for file in $(ls *.txt)
do
  echo "Text file: $file"
done

This pattern breaks on file names that contain spaces. A wildcard loop such as for file in *.txt handles such names safely.

Arithmetic Substitution

Double parentheses with a dollar sign calculate numbers:

a=12
b=5
echo "Product: $(( a * b ))"
echo "Remainder: $(( a % b ))"

Output:

Product: 60
Remainder: 2

Process Substitution

Process substitution treats a command output like a file. The syntax is <( command ). The diff command compares two listings without creating temporary files:

diff <(ls folder_one) <(ls folder_two)

Capture Both Text and Exit Status

The variable $? holds the status of the latest command. Read it right after the substitution:

result=$(grep "error" log.txt)
status=$?
echo "Search status: $status"

A status of 0 means a match exists. A status of 1 means no match. A status of 2 points to a problem such as a missing file.

Quote the Result

Wrap substitutions in double quotation marks when the output may contain spaces:

message="$(date)"
echo "$message"

Unquoted output splits into many words and may confuse later commands.

Common Mistake: Unneeded Subshell for Simple Values

Each substitution starts a small helper process. Loops that call substitution thousands of times run slower than loops that use built-in features. Prefer built-in options such as ${#text} for length instead of $(echo $text | wc -c).

Key Takeaways

  • $(command) runs a command and inserts its output.
  • Prefer $( ) over backticks for clarity.
  • Store results in variables for later use.
  • $(( )) handles math, and <( ) treats output as a file.
  • Use double quotation marks around substitutions that may hold spaces.