Skip to content
C.W.K.
Stream
Lesson 07 of 12 · published

Command Substitution and Arithmetic

~10 min · substitution, arithmetic

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

$( ) — capture command output

now="$(date +%Y-%m-%d)"
files="$(find . -name '*.py' | wc -l)"
echo "$files Python files as of $now"

$(...) runs the command, captures stdout, and substitutes the value (with trailing newlines trimmed). Always quote the result: "$(cmd)" — without quotes the value is word-split.

Backticks (legacy)

You'll see `cmd` in old scripts. Same effect, but harder to nest and easier to confuse with single quotes. Use $( ) in new code; backticks are deprecated in style guides.

(( )) — arithmetic

i=0
((i++))
((sum = a + b * 2))
((i < 10)) && echo 'still small'

Inside (( )) you don't need $ on variable names. Operators: + - * / % ** and C-style ++ -- && ||. The exit code is 0 if the result is non-zero, 1 if zero — opposite of typical C, but consistent with shell truthiness.

$(( )) — arithmetic substitution

echo "$((1 + 2))"           # 3
echo "file_$((i + 1)).txt"

Computes the value and substitutes the result. Common in filename generation and counters.

Bash 5 doesn't do floating-point

Shell arithmetic is integer only. For floats, pipe to bc -l or awk 'BEGIN{print 3.14*2}'. Most scripts don't need floats; if yours does, it's probably time to switch to Python.

Command substitution removes trailing newlines

That is convenient for one-line results but cannot preserve arbitrary text endings, and shell variables cannot contain NUL bytes. Do not capture an arbitrary filename stream into one variable.

Arithmetic commands produce an exit status

(( expression )) returns 1 for zero and 0 otherwise, so ((i++)) can stop under set -e when i starts at zero. Choose $((...)) for a value and ((...)) when status semantics are intended.

Code

Capture and compute·bash
#!/usr/bin/env bash
set -euo pipefail
lines=$(wc -l < ~/.zshrc)
doubled=$((lines * 2))
echo "$lines lines, doubled = $doubled"
now="$(date +%H:%M:%S)"
echo "snapshot at $now"

External links

Exercise

Write a one-line count.sh that prints the number of TS files and the doubled count: ts=$(find . -name '*.ts' | wc -l); echo "$ts*2 = $((ts*2))".

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.