Values from Commands: $( ) and $(( ))

$( ) runs a command and puts what it prints into another command or a variable, such as today's date in a backup's name, and $(( )) works out whole-number arithmetic, such as an age or a count plus one.

Apprentice · Unix · Linux · Updated

After this lesson you can

  • Put a command's output into a variable or a name with $( ), such as today's date with date +%F
  • Work out whole-number arithmetic with $(( )), with + - * / and %

Key takeaways

  • $(command) runs the command and puts what it prints in its place. Read it "the output of".
  • today=$(date +%F) keeps today's date, such as 2026-11-09, in a variable.
  • A dated name such as "cards-$(date +%F).tar.gz" gives every day's backup its own file. Keep it in double quotes.
  • $(( )) works out arithmetic with whole numbers. Names inside it need no $, and 17 / 5 is 3, with 17 % 5 the 2 left over.
  • $(( )) can't do decimals. 7.5 is a syntax error.

You back up your photos every Sunday into photos.tar.gz, and every Sunday the new backup replaces last week's. You'd like photos-2026-11-08.tar.gz, then photos-2026-11-15.tar.gz, one file per week. Typing the date by hand works until you mistype it, and a script that runs at night has nobody to type it at all. The date is already one command away, though: date prints it. What you need is a way to put a command's output into another command. Administrators name every backup and log file this way, and every script that counts, totals or numbers things uses its arithmetic cousin.

The examples use the card shop from Arguments: $1, $# and "$@": cd ~/terminal-practice/cards.

$( ): a command's output, in place

date with a pattern prints the parts of the date you ask for. +%F (read "plus percent F", for full date) gives the year, month and day, in an order that also sorts by date when files are listed:

date +%F
2026-11-09

Your date will be the day you run it. Now put that output inside another command. $( ) (read "the output of") runs the command between the parentheses and puts what it printed in its place, before the outer command runs. This is command substitution:

echo "Made on $(date '+%A, %B %d, %Y')"
Made on Monday, November 09, 2026

%A is the day's name, %B the month's, %d the day and %Y the year. Dates and Times, in Module 6, has the rest. You'll sometimes see the older form with backticks, `date +%F`; it does the same, but $( ) is easier to read and can go inside another one.

Keep it in a variable

name=$(command) keeps the output in a variable, so a script asks once and uses it many times:

today=$(date +%F)
echo "$today"
scripts=$(ls *.sh | wc -l)
echo "The card shop has $scripts scripts"
2026-11-09
The card shop has 6 scripts

The second pair keeps the output of a whole pipeline: ls lists the scripts, and wc -l counts the lines. A trailing new line in the output is dropped, so the value fits neatly into a sentence.

A backup with today's date in its name

Back to the problem from the start. Go up to terminal-practice and pack the card shop into an archive named after today, with tar from Many Files as One: tar and zip:

cd ~/terminal-practice
tar -czf "cards-$(date +%F).tar.gz" cards
ls *.tar.gz
cards-2026-11-09.tar.gz

Tomorrow the same line makes cards-2026-11-10.tar.gz beside it, and nothing is replaced. Run it twice on the same day, and the second run replaces that day's archive with a fresh one. The double quotes are the habit from Quotes: Double, Single and None: if the output ever has a space in it, the name stays one piece. Go back with cd cards.

$(( )): whole-number arithmetic

Bash can do sums, too. $(( )) (read "the arithmetic of") works out the arithmetic between the double parentheses and puts the answer in its place. This is arithmetic expansion. Inside it, a variable's name needs no $, and you can put $( ) inside it:

echo $(( 2026 - 1996 ))
born=1996
echo "Happy $(( $(date +%Y) - born ))th birthday, Maya!"
guests=12
echo "Cards to buy: $(( guests * 2 + 1 ))"
30
Happy 30th birthday, Maya!
Cards to buy: 25

+ adds, - subtracts, * (read "times") multiplies and / divides, with multiplication before addition, as in math class. Bash works in whole numbers only. Dividing drops what's left over, and % (read "remainder") gives it to you: 17 cards in packs of 5 make 3 full packs, with 2 cards left over.

echo $(( 17 / 5 )) $(( 17 % 5 ))
echo $(( 7.5 * 2 ))
3 2
bash: 7.5 * 2 : arithmetic syntax error: invalid arithmetic operator (error token is ".5 * 2 ")

A decimal point is an error. For money with cents, hand the sum to awk from Columns and Totals: awk: awk 'BEGIN { print 7.5 * 2 }' prints 15. zsh at a Mac's prompt knows both $( ) and $(( )).

Check yourself

2 questions to try on the lesson page.

So what

$( ) lets a script use any command's answer as a value, today's date in a backup's name above all, and $(( )) does the whole-number sums: an age, a count, one more than the last.

Key terms

Cheat sheets

Related