Command Substitution: Capture Output
The very first version of backup.sh had the date typed into the archive name, and the "same way again?" test flagged it. The fix is to let the date command supply it. To do that, a script needs to take what a command prints and use it as a value.
The rule
$( )runs a command and pastes its output in its place.
stamp="$(date +%F)" # 2026-09-25
archive="$dest/${name}-${stamp}.tar.gz"
echo "Today is $(date +%A)" # Today is Friday
count="$(find "$src" -type f | wc -l)" # how many filesWhat happens, in order:
- Bash runs the command inside
$( )in a subshell, a temporary copy of itself. - It collects everything the command prints on standard output.
- It removes trailing newlines, then puts the text where
$( )stood.
Three consequences:
- Quote it like a variable:
"$(...)". The result is split on spaces if left bare. - Anything the inner command changes about its shell, such as
cdor a variable, vanishes when the subshell ends. - Error messages are not captured; they go to the terminal. Only standard output is pasted in.
You will also meet the old backquote form, `date +%F`. It does the same job, but it is harder to read and to nest. Prefer $( ), which nests cleanly: $(basename "$(pwd)").
A cousin, process substitution, looks similar but hands over a file name instead of text, so a command that expects files can read another command's output: diff <(ls dir1) <(ls dir2).
The shortcut
Evaluate from the inside out: run the innermost $( ) in your head, write its output in its place, trim trailing newlines, and repeat until no $( ) remains.
Find the innermost command
date +%F, which prints the date as year-month-day.
Drills
Answer fast — trust the rule.
On a Friday, what does echo "Today is $(date +%A)" print?
What does x=$(printf 'hi\n\n\n'); echo "[$x]" print?
What does echo $(( $(echo 3) * 2 )) print?
A script in /home/asha runs where=$(cd /tmp; pwd), then pwd. What does the second pwd print?
Remember
$( )runs a command and pastes its output, trailing newlines removed.- Evaluate inside out, and quote the result:
"$(...)". - Trap: changes made inside
$( ), such ascd, vanish with the subshell.
