I have a shell script incrementing a variable like in the example below with set -e:

$ var=0; echo $?
$ ((var++)); echo $?
$ ((var++)); echo $?
$ ((var++)); echo $?
$ echo $var; echo $?
$ bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later  <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.    

The script exits unexpectedly. The thing is that the exact same script doesn't exit the same way when running it locally on a MacBook. The bash shell on the MacBook behaves exactly the same way when running the example above.

Does anyone have any clue what is going on here?

  • I don't see where the script is exiting?
    – Jeff Schaller
    Apr 14, 2016 at 15:06
  • You seem to have typed the commands on the prompt one by one. Instead can you post the script itself by editing your original question ?
    – MelBurslan
    Apr 14, 2016 at 15:10
  • 1
    Interesting question, I can reproduce this using a script containing #!/bin/bash; set -e; var=0; echo $?; ((var++)); echo $?; ((var++)); echo $?. I performed some other tests without set -e and it turns out that when incrementing from 0 to 1 the return code is non-zero; when you decrement from 2 to 1 does return zero; decrementing from 0 to -1 returns non-zero and incrementing from -2 to -1 returns 0.
    – Lambert
    Apr 14, 2016 at 15:15
  • That's exactly the point @Lambert I'm sure the script is exiting because of set -e, BUT, I was surprised by which step was causing the return code to be different than 0.
    – Marcel
    Apr 14, 2016 at 15:17
  • @Marcel, I am curious too, and why it happens from 0 to 1 and not from 2 to 1. Besides, I think that the local shell on the MacBook is not bash. When I run the script using sh it does not exit. You can force your script to use sh by adding the following as first line: #!/bin/sh
    – Lambert
    Apr 14, 2016 at 15:24

3 Answers 3


An arithmetic command is successful if the value of the arithmetic expression is nonzero. If the value of the expression is 0, the command fails with status 1. This allows arithmetic commands to be used in tests, as the boolean operators in shell arithmetic expressions return 0 for true and 1 for false (like in C). For example

if ((x==3)); then …

works because ((x==3)) returns 0 when $x is equal to 3 and 1 otherwise.

The postfix increment operator returns the old value of the variable. So ((var++)) returns an error status if var was previously zero.

set -e tells the shell to exit on the first command that fails. No surprises there.

To avoid unwanted errors resulting from arithmetic expressions that may legitimately have the value 0, don't use arithmetic commands, use an ordinary assignment with an arithmetic expression.

  • Is there a typo in this? I can’t make sense of the first paragraph. If Boolean operators return 0 for true, why should 0 result in a failure with status 1? Seems backwards.
    – Wildcard
    Sep 27, 2019 at 0:08
  • @Wildcard I don't see a typo, which doesn't mean there isn't one. Yes, it's backwards: C-like expressions use 0 to mean false whereas command statuses use 0 to mean true. Sep 27, 2019 at 6:02

You can always use arithmetic commands like ((var++)). If the value of var prior the assignment was 0, then to force a successful status code you can write: ((var++)) || true

Or you can write this to skip the errexit logic: ! ((var++))


I use declare -i i=0; i+=1, exit code is zero.

Earlier used to write a hack i=0; ((i++)) ||true

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .