Module 9 · Shell scripting basics
Command substitution and arithmetic
Capture a command's output into a variable with $( ), and do integer maths with $(( )) instead of reaching for a calculator.
What you will learn
- Use `$(command)` to store output in a variable or embed it in a string.
- Do integer arithmetic with `$(( ))` and know its limits.
- Combine both to build small reports.
So far variables got their values from you. The real power comes when a variable gets its value from another command. $(command) runs the command, takes whatever it printed, trims the trailing newline, and drops the text right there in your line. The old spelling with backticks, ` command , does the same but nests badly; prefer $( )`.
~% today=$(date +%Y-%m-%d)
~% echo "Backup for $today"
Backup for 2026-10-04
~% files=$(ls /etc | wc -l)
~% echo "/etc has $files entries"
/etc has 24 entries
~% echo "Kernel $(uname -r) on $(hostname), up $(cut -d' ' -f1 /proc/uptime) s"
Kernel 4.16.13 on (none), up 312.45 s
~% cp report.txt "report-$(date +%H%M).txt"
Anything that prints can feed a variable: wc -l, grep -c, date, cat file, a pipeline. Quote the substitution when you use it, "$(…)", for the same reason you quote variables: the output might contain spaces or newlines, and unquoted it gets split into words.
Arithmetic with $(( ))
The shell stores text, but $(( expression )) evaluates the expression as integer arithmetic and gives back the result as text. Inside the double parentheses you can write variable names without $, and the usual operators work: + - * / %, comparisons, parentheses. Division truncates: $(( 10 / 3 )) is 3, and $(( 10 % 3 )) is the remainder 1. There are no decimals; for those you would pipe to awk.
~% a=7; b=3
~% echo $(( a + b )) $(( a * b )) $(( a / b )) $(( a % b ))
10 21 2 1
~% echo $(( (a + b) * 2 ))
20
~% n=0; n=$(( n + 1 )); n=$(( n + 1 )); echo $n
2
~% kb=$(du -sk /etc | cut -f1)
~% echo "/etc uses $kb KB, about $(( kb / 1024 )) MB"
/etc uses 12 KB, about 0 MB
~% echo $(( 2 ** 10 ))
1024
The pattern n=$(( n + 1 )) is how you count in a loop; you will use it constantly from lesson 86 on. Comparisons inside $(( )) give 1 for true and 0 for false, but for decisions in scripts you will normally use test (next lesson) instead.
| Syntax | Meaning | Example |
|---|---|---|
$(cmd) | Output of a command | now=$(date +%T) |
$(( expr )) | Integer arithmetic | $(( total / count )) |
${var} | A variable's value | ${name}_v2 |
expr 2 + 3 | Old external calculator; spaces required | expr $a \* 2 |
One practical detail: wc -l file prints the count and the file name, while wc -l < file prints only the count, which is what you want inside $(( )). The same trick works for wc -c to get a file size in bytes without stat, which this BusyBox does not have.
Commands in this lesson
| Command | What it does |
|---|---|
var=$(command) | Store a command's output. |
echo "Now: $(date)" | Embed output inside a string. |
$(( a + b )) | Integer arithmetic. |
n=$(( n + 1 )) | Increment a counter. |
wc -l < file | Line count only, no file name. |
expr 2 + 3 | Legacy arithmetic command. |
Quiz
What does `n=$(ls /etc | wc -l)` leave in `n`?
- The text `ls /etc | wc -l`
- The number of entries in /etc
- An error: pipes are not allowed in $( )
What is `$(( 7 / 2 ))`?
- `3.5`
- `3`
- `4`
Which line correctly adds one to `count`?
- `count=count+1`
- `count=$(count + 1)`
- `count=$(( count + 1 ))`
Why quote a substitution, as in `echo "$(cat f)"`?
- To keep spaces and newlines in the output intact
- Because $( ) does not work without quotes
- To make it run faster
Practice
Write an executable script `/root/lab/l83/count.sh` that prints `Files: N`, where N is the number of entries in `/root/lab/l83/data` (use `ls | wc -l` inside `$( )`).
Write an executable script `/root/lab/l83/sum.sh` that prints the sum of its two arguments: `./sum.sh 17 25` prints `42`. (Inside a script, `$1` and `$2` are the first two arguments; more in lesson 88.)
Using command substitution, write the current year (four digits, from `date +%Y`) into `/root/lab/l83/year.txt`.
Open this lesson in the app to do the tasks in a real Linux machine and have them checked.