2
bash-3.2$ echo foo > foo.txt
bash-3.2$ if cmp foo.txt foo.txt; then echo EQUAL; fi
EQUAL
bash-3.2$ echo bar > bar.txt
bash-3.2$ if cmp foo.txt bar.txt; then echo EQUAL; fi
foo.txt bar.txt differ: char 1, line 1

But cmp returns 0 for equal, returns 1 for different, is the explanation that the if statement in bash is executed for a return value of 0, or what is it?

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Niklas Rosencrantz
  • 4,112
  • 6
  • 36
  • 58
  • Relevant, possibly even dupes: [What is the value of boolean(True and False) in Python concept and shell concept?](https://unix.stackexchange.com/q/429039) and [The paradox of logical AND (&&) and OR (||) in a bash script to check the successful execution of command (exit code of 0 is interpreted as true)](https://unix.stackexchange.com/q/632670) – terdon Nov 18 '22 at 19:08
  • Thanks, what I was looking was that somebody confirms the counterintuitive idea that 0 is truthy _with the exit status of a processes, yes, 0 is truthy, and anything else is falsy._ – Niklas Rosencrantz Nov 19 '22 at 09:17
  • That's not just bash, that's standard C exit statuses (which is _why_ it's true for bash; the shell is, after all, there to glue between different programs written in C). 0 means success, everything else is a different error code so your application can distinguish between individual errors. Error code 0 == no error == success. – Charles Duffy Nov 19 '22 at 21:54
  • @CharlesDuffy Yes but for `cmp` it is slightly different: 0 means no difference between the two inputs, and 1 means that there is a difference, exit codes > 1 are errors. In my case, I want to check for difference in files with cmp. (Which can be done in many ways, but I think it is easiest to use cmp). So, I don't want my script to fail when it is sometimes expected that there is a difference between two files. – Niklas Rosencrantz Nov 20 '22 at 12:07
  • Who said anything about your script "failing" if `cmp` does? Are you using `set -e`? [Don't do that.](https://mywiki.wooledge.org/BashFAQ/105#Exercises) – Charles Duffy Nov 20 '22 at 14:52
  • If any command inside an `if` having a nonzero exit status, `if` would be useless. Consequently, `set -e` ignores the exit status of "checked" commands -- which is to say, roughly, commands whose exit status is used for branching purposes. Unfortunately, the full definition is deeply nuanced and unintuitive, which is part of why `set -e` is such a bad idea, as gone into in more detail in the FAQ linked above. (I linked to just the exercises section, but the parable above it describes _why_ `set -e` behavior came to be so hard to predict or understand). – Charles Duffy Nov 20 '22 at 14:53

1 Answers1

8

Yes. In bash (and other shells), a command that exits with status 0 is considered "success", and any other exit status is considered "failure".

The bash if command doesn't strictly work with a "conditional" expression. The syntax is:

$ help if
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
    Execute commands based on conditional.

    The `if COMMANDS' list is executed.  If its exit status is zero, then the
    `then COMMANDS' list is executed.  Otherwise ...

It branches based on the exit status of the COMMANDS it's given.

The typical commands you see most commonly in an if statement are the [ builtin command and the [[...]] construct. These commands work just the same way: exit with status 0 for "success/true" or non-zero for "failure/false" and, like cmp or any other command, can be used just as well inside or outside if/while/until statements.

glenn jackman
  • 84,176
  • 15
  • 116
  • 168
  • 3
    May be worth spelling out the _reason_ why shells consider 0 true and non-zero false (opposite to most programming languages, boolean logic, &c): it allows many different types of failure (from being unable to find a file, or running out of disk space or memory, or the process being killed, or lack of necessary permissions…). Since there's only one type of success, it makes sense to make that zero, and use non-zero status codes for the various types of failure. – gidds Nov 19 '22 at 13:38