Scripts constantly need dates, counts and computed values from other commands.
Command substitution $(command) runs the command and replaces itself with the command's stdout, minus trailing newlines. Use it to store results: today=$(date +%F), n=$(wc -l < file). The old backtick form does the same but nests badly; prefer $( ), which nests cleanly: $(dirname "$(readlink -f "$0")").
Quote the substitution when using it as an argument, "$(cmd)", or the output will be word-split and globbed like any unquoted expansion. In a plain assignment x=$(cmd) no quotes are needed, but they do no harm.
Arithmetic expansion $(( expr )) evaluates integer math with C-like operators: + - * / % **, comparisons, &&, ||, bit operators and the ternary ?:. Variables inside need no $. Division truncates; bash has no floating point, so reach for awk or bc when you need decimals.
The command form (( expr )) evaluates without printing and returns success when the result is non-zero, which makes it ideal for conditions and counters: (( count++ )), if (( n % 2 == 0 )). Note that (( x++ )) returns failure when x was 0, which matters under set -e; write x=$(( x + 1 )) there.
Numbers with a leading zero, like 08, are read as octal and error out; strip zeros or write 10#$n.
Example
today=$(date +%F)
entries=$(ls / | wc -l)
echo "Today is $today; / has $entries entries"
kernel="$(uname -r)"
echo "Running kernel $kernel"
lines=$(printf 'a\nb\n\n\n') # trailing newlines are stripped
echo "${#lines}" # 3 ("a", newline, "b")
x=7 y=3
echo $(( x * y + 1 )) # 22
echo $(( x / y )) $(( x % y )) # 2 1 (integers only)
echo $(( 2 ** 10 )) # 1024
(( x > y )) && echo "x wins" # x wins
month=08
echo $(( 10#$month + 1 )) # 9 (force base 10, avoid octal)
awk 'BEGIN { printf "%.2f\n", 10 / 3 }' # 3.33 (floats need another tool)Remember
- $(cmd) captures stdout without trailing newlines; quote it as an argument
- $(( )) for integer math, (( )) for arithmetic conditions
- No floats in bash: use awk or bc
Watch out for
- Leading zeros: $(( 08 + 1 )) fails because 08 is parsed as an invalid octal number.