Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sh doesn't like $(( 08 % 2 ))

832 views
Skip to first unread message

Adam Funk

unread,
Jul 3, 2014, 9:14:16 AM7/3/14
to
Background: I'm fiddling with a cron.daily job that I want to run on
alternate days, so I want to test the output of `date +%j` for
evenness.

I figured the best way to check my if-test would be to use +%s, so I
wrote the following (/bin/sh is dash on my system, but I could use
another shell if it would be useful):

#v+
#!/bin/sh
SEC=`date +%S`
if [ $(( $SEC % 2 )) -eq 0 ]
then
echo "$SEC is even"
else
echo "$SEC is odd"
fi
#v-

This works 58/60 of the time, but barfs on 08 and 09:

$ ./odd-even-date.sh
./odd-even-date.sh: 4: ./odd-even-date.sh: arithmetic expression: expecting EOF: " 08 % 2 "

$ ./odd-even-date.sh
./odd-even-date.sh: 4: ./odd-even-date.sh: arithmetic expression: expecting EOF: " 09 % 2 "

I'm guessing it's because it expects numbers starting with 0 to be
octal, but I can't remember how to tell it to treat them as decimal in
this case. Suggestions?

(Well, `date +%j` currently returns 184, so I have some time before my
cron job will break. It might not even break --- I can't remember
whether %j gets padded with zeros or not. But I'd still like to know
how to de-octalize this thing.)

Thanks,
Adam



--
It would be unfair to detect an element of logic in the siting of the
Pentagon alongside the National Cemetery, but the subject seems at
least worthy of investigation. --- C Northcote Parkinson

Stachu 'Dozzie' K.

unread,
Jul 3, 2014, 9:30:57 AM7/3/14
to
On 2014-07-03, Adam Funk <a24...@ducksburg.com> wrote:
> Background: I'm fiddling with a cron.daily job that I want to run on
> alternate days, so I want to test the output of `date +%j` for
> evenness.
>
> I figured the best way to check my if-test would be to use +%s, so I
> wrote the following (/bin/sh is dash on my system, but I could use
> another shell if it would be useful):
>
> #v+
> #!/bin/sh
> SEC=`date +%S`
> if [ $(( $SEC % 2 )) -eq 0 ]
[...]
> $ ./odd-even-date.sh
> ./odd-even-date.sh: 4: ./odd-even-date.sh: arithmetic expression: expecting EOF: " 09 % 2 "
>
> I'm guessing it's because it expects numbers starting with 0 to be
> octal, but I can't remember how to tell it to treat them as decimal in
> this case. Suggestions?

You may want to strip leading zeros (there could be two of them for %j
you want, so you want stripping done twice):
#v+
SEC=`date +%S`
SEC=${SEC#0}
SEC=${SEC#0}
#v-

GNU date also has flags, so you could just use them if on Linux:
#v+
SEC=`date +%_S`
#v-

> (Well, `date +%j` currently returns 184, so I have some time before my
> cron job will break. It might not even break --- I can't remember
> whether %j gets padded with zeros or not. But I'd still like to know
> how to de-octalize this thing.)

For this, GNU date (again, an extension) has `-d' option:
#v+
$ date -d '2014/02/01' +%j
032
$ date -d '2014/02/01' +%_j
32
#v-

--
Secunia non olet.
Stanislaw Klekot

Kaz Kylheku

unread,
Jul 3, 2014, 9:55:45 AM7/3/14
to
On 2014-07-03, Adam Funk <a24...@ducksburg.com> wrote:
> Background: I'm fiddling with a cron.daily job that I want to run on
> alternate days, so I want to test the output of `date +%j` for
> evenness.

Well, of course. 08 is octal. (Moreover, it is invalid octal.)

> SEC=`date +%S`
> if [ $(( $SEC % 2 )) -eq 0 ]

Try:

$(( (1$SEC - 100) % 2)) -eq 0 ]


Janis Papanagnou

unread,
Jul 3, 2014, 10:03:03 AM7/3/14
to
On 03.07.2014 15:14, Adam Funk wrote:
> Background: I'm fiddling with a cron.daily job that I want to run on
> alternate days, so I want to test the output of `date +%j` for
> evenness.

Some crons already allow a finer time specification, includnig "every other"
instances of time. From my man page...

Step values can be used in conjunction with ranges. Following a range
with ``/<number>'' specifies skips of the number's value through the
range. For example, ``0-23/2'' can be used in the hours field to spec‐
ify command execution every other hour (the alternative in the V7 stan‐
dard is ``0,2,4,6,8,10,12,14,16,18,20,22''). Steps are also permitted
after an asterisk, so if you want to say ``every two hours'', just use
``*/2''.

>
> I figured the best way to check my if-test would be to use +%s, so I
> wrote the following (/bin/sh is dash on my system, but I could use
> another shell if it would be useful):

With modern shells (ksh, zsh, bash) you can force decimal interpretation
of numbers by preceding them with "10#", as in SEC=10#$( date +%S ) .

Janis

Adam Funk

unread,
Jul 3, 2014, 10:07:33 AM7/3/14
to
On 2014-07-03, Stachu 'Dozzie' K. wrote:

> On 2014-07-03, Adam Funk <a24...@ducksburg.com> wrote:
>> Background: I'm fiddling with a cron.daily job that I want to run on
>> alternate days, so I want to test the output of `date +%j` for
>> evenness.
>>
>> I figured the best way to check my if-test would be to use +%s, so I
>> wrote the following (/bin/sh is dash on my system, but I could use
>> another shell if it would be useful):
>>
>> #v+
>> #!/bin/sh
>> SEC=`date +%S`
>> if [ $(( $SEC % 2 )) -eq 0 ]
> [...]
>> $ ./odd-even-date.sh
>> ./odd-even-date.sh: 4: ./odd-even-date.sh: arithmetic expression: expecting EOF: " 09 % 2 "
>>
>> I'm guessing it's because it expects numbers starting with 0 to be
>> octal, but I can't remember how to tell it to treat them as decimal in
>> this case. Suggestions?
...
> GNU date also has flags, so you could just use them if on Linux:
> #v+
> SEC=`date +%_S`
> #v-

Doh, it's right there in the man page after the % codes!

$ date +'%S:%_S:%-S'
00: 0:0

Thanks!


--
The Nixon I remembered was absolutely humorless; I couldn't imagine
him laughing at anything except maybe a paraplegic who wanted to vote
Democratic but couldn't quite reach the lever on the voting machine.
--- Hunter S Thompson

Adam Funk

unread,
Jul 3, 2014, 10:09:16 AM7/3/14
to
On 2014-07-03, Stachu 'Dozzie' K. wrote:

I remembered that one; "so I have some time" was kind of a joke! But
thanks for the help.


--
It is probable that television drama of high caliber and produced by
first-rate artists will materially raise the level of dramatic taste
of the nation. (David Sarnoff, CEO of RCA, 1939; in Stoll 1995)

Adam Funk

unread,
Jul 3, 2014, 10:08:31 AM7/3/14
to
Thanks. I've already gone with the `date +%-j` solution, though.


--
Dear Ann [Landers]: if there's an enormous rash of necrophilia that
happens in the next year because of this song, please let me know.
99.9% of the rest of us know it's a funny song! --- Alice Cooper

Dave Sines

unread,
Jul 3, 2014, 1:38:50 PM7/3/14
to
Adam Funk <a24...@ducksburg.com> wrote:
> Background: I'm fiddling with a cron.daily job that I want to run on
> alternate days, so I want to test the output of `date +%j` for
> evenness.
>
> I figured the best way to check my if-test would be to use +%s, so I
> wrote the following (/bin/sh is dash on my system, but I could use
> another shell if it would be useful):
>
> #v+
> #!/bin/sh
> SEC=`date +%S`
> if [ $(( $SEC % 2 )) -eq 0 ]
> then
> echo "$SEC is even"
> else
> echo "$SEC is odd"
> fi
> #v-
>
> This works 58/60 of the time, but barfs on 08 and 09:

Treat $SEC as a string and use a globbing pattern to check the last
character (even == ends with 0, 2, 4, 6 or 8):

SEC=$(date +%j)
case $SEC in
*[02468] ) echo "$SEC is even" ;;
* ) echo "$SEC is odd" ;;
esac

Adam Funk

unread,
Jul 4, 2014, 4:15:21 PM7/4/14
to
On 2014-07-03, Janis Papanagnou wrote:

> On 03.07.2014 15:14, Adam Funk wrote:
>> Background: I'm fiddling with a cron.daily job that I want to run on
>> alternate days, so I want to test the output of `date +%j` for
>> evenness.
>
> Some crons already allow a finer time specification, includnig "every other"
> instances of time. From my man page...
>
> Step values can be used in conjunction with ranges. Following a range
> with ``/<number>'' specifies skips of the number's value through the
> range. For example, ``0-23/2'' can be used in the hours field to spec‐
> ify command execution every other hour (the alternative in the V7 stan‐
> dard is ``0,2,4,6,8,10,12,14,16,18,20,22''). Steps are also permitted
> after an asterisk, so if you want to say ``every two hours'', just use
> ``*/2''.

I can do that in a crontab, but not in a cron.daily file; I'm happy
with this solution because the if...then...else...fi puts either the
"real" job output or a "no $whatever today" in the anacron e-mail.


>> I figured the best way to check my if-test would be to use +%s, so I
>> wrote the following (/bin/sh is dash on my system, but I could use
>> another shell if it would be useful):
>
> With modern shells (ksh, zsh, bash) you can force decimal interpretation
> of numbers by preceding them with "10#", as in SEC=10#$( date +%S ) .

Thanks, I'll file that for future reference.


--
Specifications are for the weak & timid!
--- Klingon Programmer's Guide

Dr J R Stockton

unread,
Jul 4, 2014, 3:36:16 PM7/4/14
to
In comp.unix.shell message <8i1g8bx...@news.ducksburg.com>, Thu, 3
Jul 2014 14:14:16, Adam Funk <a24...@ducksburg.com> posted:

>
>(Well, `date +%j` currently returns 184, so I have some time before my
>cron job will break. It might not even break --- I can't remember
>whether %j gets padded with zeros or not. But I'd still like to know
>how to de-octalize this thing.)

That will fail to give alternate days at three out of every four year
rollovers in our probable lifetimes.

Take the number of seconds from epoch (1970.0 GMT), add about 43200 (I
assume you are in Europe; those resident in America (north or south)
should add about half as much again, I think. Integer divide by 86400,
and test the least significant bit of the result by the method of your
choice.

--
(c) John Stockton, nr London, UK. E-mail, see Home Page. Turnpike v6.05.
Website <http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc. : <http://www.merlyn.demon.co.uk/programs/> - see in 00index.htm
Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.

Adam Funk

unread,
Jul 5, 2014, 4:12:35 PM7/5/14
to
On 2014-07-04, Dr J R Stockton wrote:

> In comp.unix.shell message <8i1g8bx...@news.ducksburg.com>, Thu, 3
> Jul 2014 14:14:16, Adam Funk <a24...@ducksburg.com> posted:
>
>>
>>(Well, `date +%j` currently returns 184, so I have some time before my
>>cron job will break. It might not even break --- I can't remember
>>whether %j gets padded with zeros or not. But I'd still like to know
>>how to de-octalize this thing.)
>
> That will fail to give alternate days at three out of every four year
> rollovers in our probable lifetimes.

True, but it's more accurate than */2 in the daymo column of a
crontab.


> Take the number of seconds from epoch (1970.0 GMT), add about 43200 (I
> assume you are in Europe; those resident in America (north or south)
> should add about half as much again, I think. Integer divide by 86400,
> and test the least significant bit of the result by the method of your
> choice.

Thanks.


--
Civilization is a race between catastrophe and education.
[H G Wells]
0 new messages