mimoralea mimoralea - 27 days ago 4x
Bash Question

Expr and date in shell and in a variable

So, I do:

expr `date +%d` - 1

In sh shell and it correctly respond

But if I want to store that in a variable:

-sh-4.2# NUMBER=expr `date +%d` - 1
-sh: 12: command not found
-sh-4.2# NUMBER=$((expr `date +%d` - 1))
-sh: expr 12 - 1: syntax error in expression (error token is "12 - 1")
-sh-4.2# NUMBER="expr `date +%d` - 1"
-sh-4.2# echo $NUMBER
expr 12 - 1
-sh-4.2# $NUMBER

It just doesn't give me what I'm looking for. I want:

echo $NUMBER

to say
, not to evaluate to 11?

My questions are:

  1. Why does my first attempt not work?

  2. How can I make it happen?

BTW, I'm limited to /bin/sh
GNU bash, version 4.2.10(1)-release (mipsel-unknown-linux-uclibc)

AND, date is very limited.
BusyBox v1.19.4 (2013-10-30 00:56:51 PDT) multi-call binary.

Although, it is bash it is limited since it is an embedded platform.


I think this is what you're looking for:

$ NUMBER=$(expr `date +%d` - 1) 
$ echo $NUMBER

This works because expr is a command which is evaluated. To get the output of an evaluated command, you can use $() command expansion or backticks


$ NUMBER=$(expr $(date +%d) - 1)
$ echo $NUMBER

This is pretty much equivalent to the first example. Note $() is preferable to backticks because it is easily nestable without escaping quotes.


$ NUMBER=$(($(date +%d) - 1))
$ echo $NUMBER

We can also do arithmetic directly in the shell without the expr command, using $(( )) arithmetic expansion. See the Arithmetic Expansion section of the Advanced Bash-Scripting Guide


Since you're using busybox, you can use this mouthful to do the date arithmetic correctly, even when it is the 1st of the month:

$ type date
date is aliased to `busybox date'
$ NUMBER=$(date -D %s -d $(($(date +%s) - 86400)) +%d)
$ echo $NUMBER

This breaks in 2038 though due to the Unix Epoch Year 2038 problem, so please don't implement this in a nuclear power station or space station or something ;-)