3

I was trying to think of a quick and illustrative way to generate a non-successful exit status and thought dividing by zero with the bc would be a good idea.

I was suprised to discover that although it does generate a runtime error, the exit status is still 0:

$ echo 41 + 1 | bc
42
$ echo $?
0
$ echo 42/0 | bc
Runtime error (func=(main), adr=6): Divide by zero
$ echo $?
0
  • Why does the bc utility not fail with a non-zero exit status?

Note: For a quick non-zero exit status I'm using return 1

Also, from shell-tips:

$ expr 1 / 0
expr: division by zero
$ echo $?
2
  • I would use ls nosuchfile for the illustration, by the way. Or if I want to show how non-zero exit statuses do have conventional meanings, I would set up as follows: echo hello > file1; echo hello > file2; echo goodbye > file3 and then show the exit status for cmp file1 file2, cmp file1 file3, cmp file1 file4. – Wildcard Apr 4 '17 at 0:22
  • You cannot devide by 0? The answer is unlimited? – Xorifelse Apr 4 '17 at 0:23
6

bc implementations differ a bit in their return status, but the general idea is that if you supply valid input then bc exits with the status 0. 42/0 is valid input: there's no read error, and it's even a syntactically valid expression, so bc returns 0. If you passed a second line with another operation, bc would perform it. This is different from expr whose purpose is to evaluate a single arithmetic expression; here the outcome of that single expression determines the return status.

The most straightforward way to generate an exit status that indicates failure is to call false. Things like expr 1 / 0 only have their place in obfuscated programming contests.

| improve this answer | |
6

Look in the spec; this is expected behavior.

All of the input was read correctly by bc, so it produced exit status 0.

If you run bc on a non-existent file, like bc nosuchfile, you will get some other exit status.


For illustrating a non-zero exit status, I would either compare ls somefile and ls nosuchfile, or I would show how exit statuses 1 and 2 are conventionally used (1 for expected error or failure status, 2 for unexpected error) like so:

$ echo hello > file1
$ echo hello > file2
$ echo goodbye > file3
$ cmp -s file1 file2
$ echo $?
0
$ cmp -s file1 file3
$ echo $?
1
$ cmp -s file1 file4
$ echo $?
2
$ 
| improve this answer | |
  • 1
    @user367890, yes, thanks. I considered adding that to the answer but decided against it, since ultimately it just says, "The reasons are historical." But I will comment that POSIX formalizes what is already standard in practice: requiring behavior different from that of all existing implementations isn't the goal, even if it that behavior might seem like a better design. So "historical reasons" actually describes much of POSIX. – Wildcard Apr 4 '17 at 1:18
  • 2
    It is accepted behaviour, but not mandated nor recommended (so I wouldn't put expected here). The exit status is unspecified if there's an error. Here, regardless of POSIX conformance, in the case of GNU bc, I'd argue it's a bug as upon that division by zero (but also upon syntax error), it's a fatal error, bc doesn't process further input. – Stéphane Chazelas Apr 5 '17 at 8:24
  • @Wildcard: Yes, but a non zero exit code does not indicate there was a failure reading – it could, but an implementation could also exit with <> 0 on for example n / 0. As the Q is “Why does bc exit 0 when dividing by 0?” – one should likely point out that this is an invalid statement. From how I read it, even failure to read input file could also result in exit code 0 as it is unspecified. Perhaps I am wrong. – user367890 Apr 5 '17 at 22:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.