== An interesting picky difference between Bourne shells Today we ran into an interesting bug in one of our internal shell scripts. The script had worked for years on our Solaris 10 machines, but on a new OmniOS fileserver it suddenly reported an error: .pn prewrap on > script[77]: [: 232G: arithmetic syntax error Cognoscenti of ksh error messages have probably already recognized this one and can tell me the exact problem. To show it to everyone else, here is line 77: > if [ "$qsize" -eq "none" ]; then > .... In a strict POSIX shell, this is an error because _test_'s _-eq_ operator is specifically for comparing *numbers*, not strings. What we wanted is the _=_ operator. What makes this error more interesting is that the script had been running for some time on the OmniOS fileserver without this error. However, until now the _$qsize_ variable had always had the value '_none_'. So why hadn't it failed earlier? After all, '_none_' (on either side of the expression) is just as much of not-a-number as '_232G_' is. The answer is that this is a picky difference between shells in terms of how they actually behave. Bash, for example, always complains about such misuse of _-eq_; if either side is not a number you get an error saying '_integer expression expected_' (as does Dash, with a slightly different error). But on our OmniOS, _/bin/sh_ is actually ksh93 and ksh93 has a slightly different behavior. Here: > $ [ "none" -eq "none" ] && echo yes > yes > $ [ "bogus" -eq "none" ] && echo yes > yes > $ [ "none" -eq 0 ] && echo yes > yes > $ [ "none" -eq "232G" ] && echo yes > /bin/sh: [: 232G: arithmetic syntax error The OmniOS version of ksh93 clearly has some sort of heuristic about number conversions such that strings with no numbers are silently interpreted as '0'. Only invalid numbers (as opposed to things that aren't numbers at all) produce the 'arithmetic syntax error' message. Bash and dash are both more straightforward about things (as is the FreeBSD _/bin/sh_, which is derived from ash). Update: my description isn't actually what ksh93 is doing here; per opk's comment, it's actually interpreting the _none_ and _bogus_ as variable names and giving them a value of 0 when unset. Interestingly, the old Solaris 10 _/bin/sh_ seems to basically be calling _atoi()_ on the arguments for _-eq_; the first three examples work the same, the fourth is silently false, and '_[ 232 -eq 232G ]_' is true. This matches the 'let's just do it' simple philosophy of the original Bourne shell and _test_ program and may be authentic original V7 behavior. (Technically this is a difference in _test_ behavior, but _test_ is a builtin in basically all Bourne shells these days. Sometimes the standalone _test_ program in _/bin_ or _/usr/bin_ is actually a shell script to invoke the builtin.)