Shell – Peculiar Solaris integer comparison behaviour

shellsolaristest

This one caught me unawares!

We have a Solaris machine (version: SunOS 5.8) hosting a pivotal script/process which has been running for many years without complaint. We recently had cause to have a look under the hood and found a test condition that — as far as I can tell — shouldn't work, but for some reason does:

$ sh
$ [ 90% -gt 95 ]; echo $?
1
$ [ 96% -gt 95 ]; echo $?
0

What?! It doesn't appear to be a fluke:

$ [ 96% -lt 95 ]; echo $?
1
$ [ 96% -eq 96 ]; echo $?
0   

It's not just the % either:

$ [ 96blah -eq 96 ]; echo $?
0
$ [ 1.2 -gt 1 ]; echo $?
1

It appears to be like this on SunOS 5.8, 5.9 and 5.10 but I otherwise haven't noticed this before. Unfortunately, I don't appear to have another non-Solaris system easily at hand to check that doesn't have /bin/sh symlinked to bash (which isn't so liberal with its interpretation).

So, sloppy code aside (the x% is passed by variable and probably wasn't noticed), why is the standard (presumably Bourne?) shell treating these test arguments as integers by truncating them? Is this documented behaviour? I couldn't see anything in man sh but may have missed something.

NB: This was actually a secondary boo-boo within another strange test condition, but that probably deserves its own question.

Best Answer

The standard says that test operators like -gt compare it's operands as integers, but it does not mention what should happen when the supplied strings are no integers. So the observed behavior is fully correct. BTW: it is also compatible with historic UNIX behavior.

/bin/sh of course is not linked to bash, as bash is not standard compliant enough and probably would cause a lot of scripts to fail.

In 2010, with the development of Solaris 10, /bin/sh was replaced by ksh93 and even though ksh is much more compatible to the Bourne Shell than bash, this caused Solaris to be unable to have / and /usr in different filesystems which was no problem before. Note that ksh93 loads dynamic libraries from /usr.

Related Question