ayifos ayifos - 3 months ago 11
Bash Question

Why do people add `true` before incrementing or decrementing a variable in sh?

I have a script which contains the

true $(( var-- ))
statement inside a while loop what does this mean? It could be simply
$(( var-- ))
without "true". But why in this way? What is the significance of true in that?


To complement λuser's helpful answer:

The true in true $(( var-- )) is a way to perform a variable assignment without causing (additional) side effects:

  • An arithmetic expansion - $(( ... )) - expands to (is replaced with) the result of the calculation/assignment.
  • Using an arithmetic expansion as a stand-alone statement causes the shell to interpret its result as a command to execute, as user λuser notes - which is usually undesired.
  • By passing an arithmetic expansion as an argument to true, its result is effectively ignored, because true ignores any arguments you pass to it.


  • -- and ++ aren't POSIX-compliant, as λuser points out.
  • The preferred way to apply the expand-but-ignore-all-arguments trick is to use : rather than true; : is the null utility, whose express purpose is to expand, but otherwise ignore its arguments, while always setting the exit code to 0.

Thus, to remain POSIX-compliant[1] (when used in a script targeting /bin/sh), you should use:

: $(( var-=1 ))

However, if you can assume bash, ksh, or zsh, you can use --, and also simply omit the $ to get an arithmetic evaluation that does not expand to anything:

(( var-- ))  

Or, to ensure exit code 0 (the exit code usually doesn't matter in the body of a loop):

: (( var-- ))

Note that (( ... )) sets its exit code to 1 if the calculation results in 0, and to 0 for any nonzero result, which allows direct use in conditionals (if (( ... )); then ...), as an arithmetic/Boolean alternative to [ ... ] / [[ ... ]] conditionals.

[1] Note that POSIX does allow for -- and even (( ... )), but only as optional extensions, so you cannot assume their presence on all platforms.