James PK's Technical Journal

[ Home | Journal ]


Tue, 18 Feb 2014

Bash - Arithmetic Related Error

I used a date calculation in a script, that failed:

jamespk@hal:~$ let day_of_year=$(date "+%j")
bash: let: day_of_year=049: value too great for base (error token is "049")

It turns out bash is treating the number as octal because of the leading zero.

A solution is to specify the base-10 prefix
jamespk@hal:~$ let day_of_year=10#$(date "+%j")
jamespk@hal:~$ echo $day_of_year
49

posted at: 00:00 | path: /shell | permanent link to this entry


Sun, 26 Jan 2014

Bash - Testing the success of commands

When I started bash scripting I typically wrote out the sequential code and ever hopeful, assumed that after a couple of tests that the code will always succeed. Such as in this example where it's assumed a file has been scp-ed therefore the local copy can now be deleted:

#do my important scp job
scp user@host myfile 

#assume that SCP was OK, so delete local file
rm myfile

A quick test or two might prove that the script is successful but in reality, whatever happens to scp, we delete the file anyway. In the eventuality that scp fails, we probably want to keep the file. Bash stores the return status of commands is stored in the $? variable. Usually the result value of 0 indicates success:

if [ "$?" -eq "0" ] ; then
    #sucesss(?)

if [ "$?" -ne "0" ]
    #failed

Re-visiting the scp example,we can now check the return status

#do my important scp job
scp user@host myfile 
if [ "$?" -ne "0" ]
        #failed
        echo "scp error - exiting"
        exit
#should be ok to delete files
rm #etc

The return value can be easily be printed/echo-ed:

 
jamespk@hal:~$ [ "abc" = "abc" ];echo $?
0
jamespk@hal:~$ [ "abc" = "xyz" ];echo $?
1
jamespk@hal:~$ test -d "$HOMEz" ;echo $?
1

Care needs to be taken when checking the return value, particular with pipes, as we see a value of 2 returned in the first example but when used with a pipe we get 0.

jamespk@hal:~$ ls does-not-exist
ls: cannot access does-not-exist: No such file or directory
jamespk@hal:~$ echo $?
2
jamespk@fuji:~$ ls does-not-exist | head
ls: cannot access x: No such file or directory
jamespk@fuji:~$ echo $?
0

This is where the $PIPESTATUS array comes in handy:

jamespk@fuji:~$ ls x | head
ls: cannot access x: No such file or directory
jamespk@fuji:~$ echo $PIPESTATUS
2
jamespk@fuji:~$ ls x | head 
ls: cannot access x: No such file or directory
jamespk@fuji:~$ echo ${PIPESTATUS[@]}
2 0 

posted at: 00:00 | path: /shell | permanent link to this entry


Made with Pyblosxom