Why 0 is true but false is 1 in the shell?

bash builtin true/false
shell true/false
if else bash
bash false value
bash boolean expressions
bash if true
boolean bash condition
bash script if boolean is true
false; echo $?

The above will output 1, which is contradictory with all other programming languages I know.

Any reason in this?

It's a convention, but a particularly useful one when you think about it. In general, if a program succeeds that's all you need to know. If it fails, however, you might need to know all kinds of information about the failure - why it happened, how to fix it, etc. Having zero mean 'success' and non-zero mean failure lets you can check pretty easily for success, and investigate the particular error for more details if you want to. A lot of APIs and frameworks have a similar convention - functions that succeed return 0 and and those that fail give back an error code describing the particular failure case.

What is a best practice to represent a boolean value in a shell script , That is, what a particular thing (like true or false ) means depends a great prints "1" if false; then echo "yep"; else echo "nope"; fi # prints "nope" of the more usual zero=false, nonzero=true convention, but for exit statuses it  Setting the shell argument to a true value causes subprocess to spawn an intermediate shell process, and tell it to run the command. In other words, using an intermediate shell means that variables, glob patterns, and other special shell features in the command string are processed before the command is run.

Bash is a programming (scripting) language, but it's also a shell and a user-interface. If 0 was error, then the program could only present one kind of error.

However in Bash, any nonzero value is an error, and we may use any number from 1-255 to represent an error. This means we can have many different kinds of errors. 1 is a general error, 126 means that a file cannot be executed, 127 means 'command not found', etc. Here's a list of Bash Exit Codes With Special Meanings showing some of the most common exit codes.

There are also many kinds of success (exit status is 0). However, a success will allow you to proceed to the next step—you can like print results to a screen, or execute a command, etc.

How does bash test 'false'?, Bash is a programming (scripting) language, but it's also a shell and a user-​interface. If 0 was error, then the program could only present one kind of error. “0” is TRUE because it is a STRING and it has a length of 1. 0 is FALSE because it is a number and that number is 0. In PowerShell, any number which evaluates to 0 is FALSE and every non-zero number is TRUE.

There are two related issues here.

First, the OP's question, Why 0 is true but false is 1 in the shell? and the second, why do applications return 0 for success and non-zero for failure?

To answer the OP's question we need to understand the second question. The numerous answers to this post have described that this is a convention and have listed some of the niceties this convention affords. Some of these niceties are summarized below.

Why do applications return 0 for success and non-zero for failure?

Code that invokes an operation needs to know two things about the exit status of the operation. Did the operation exit successfully? [*1] And if the operation does not exit successfully why did the operation exit unsuccessfully? Any value could be used to denote success. But 0 is more convenient than any other number because it is portable between platforms. Summarizing xibo's answer to this question on 16 Aug 2011:

Zero is encoding-independent.

If we wanted to store one(1) in a 32-bit integer word, the first question would be "big-endian word or little-endian word?", followed by "how long are the bytes composing a little-endian word?", while zero will always look the same.

Also it needs to be expected that some people cast errno to char or short at some point, or even to float. (int)((char)ENOLCK) is not ENOLCK when char is not at least 8-bit long (7-bit ASCII char machines are supported by UNIX), while (int)((char)0) is 0 independent of the architectural details of char.

Once it is determined that 0 will be the return value for success, then it makes sense to use any non-zero value for failure. This allows many exit codes to answer the question why the operation failed.

Why 0 is true but false is 1 in the shell?

One of the fundamental usages of shells is to automate processes by scripting them. Usually this means invoking an operation and then doing something else conditionally based on the exit status of the operation. Philippe A. explained nicely in his answer to this post that

In bash and in unix shells in general, return values are not boolean. They are integer exit codes.

It's necessary then to interpret the exit status of these operations as a boolean value. It makes sense to map a successful (0) exit status to true and any non-zero/failure exit status to false. Doing this allows conditional execution of chained shell commands.

Here is an example mkdir deleteme && cd $_ && pwd. Because the shell interprets 0 as true this command conveniently works as expected. If the shell were to interpret 0 as false then you'd have to invert the interpreted exit status for each operation.

In short, it would be nonsensical for the shell to interpret 0 as false given the convention that applications return 0 for a successful exit status.


[*1]: Yes, many times operations need to return more than just a simple success message but that is beyond the scope of this thread.

See also Appendix E in the Advanced Bash-Scripting Guide

boolean - Why 0 is true but false is 1 in the shell?, In Unix-like operating systems, true and false are commands whose only function is to always return with a predetermined exit status. Programmers and scripts often use the exit status of a command to assess success (exit status zero) or failure (non-zero) values of command success, because true returns 0, and false returns 1. Why 0 is true but false is 1 in the shell? One of the fundamental usages of shells is to automate processes by scripting them. Usually this means invoking an operation and then doing something else conditionally based on the exit status of the operation. Philippe A. explained nicely in his answer to this post that

The one fundamental point I find important to understand is this. In bash and in unix shells in general, return values are not boolean. They are integer exit codes. As such, you must evaluate them according to the convention saying 0 means success, and other values mean some error.

With test, [ ] or [[ ]] operators, bash conditions evaluate as true in case of an exit code of 0 (the result of /bin/true). Otherwise they evaluate as false.

Strings are evaluated differently than exit codes:

if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi

if [ -z "" ] ; then echo null ; fi

The (( )) arithmetic operator interprets 1 and 0 as true and false. But that operator cannot be used as a complete replacement for test, [ ] or [[ ]]. Here is an example showing when the arithmetic operator is useful:

for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
  if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done

true and false (commands), 0 == False; Not 0 == True. and that is correct for those languages. BASH is a shell script language for launching programs and automating  The boolean values true and false can both be implicitly converted to the int type, thus yielding 1 and 0 respectively. So yes, and a return value of true can be considered 1 and false as 0

It's just a convention that a 0 exit code means success. EXIT_SUCCESS will be 0 on almost every modern system.

EDIT:

"why both test 0 and test 1 returns 0(success) ?"

That's a completely different question. The answer is that passing a single argument to test always results in success unless that argument is the null string (""). See the Open Group documentation.

Bash: Why would [[ $1 == true]] || return 1 work but not [[ $1 == false]], In SOME Korn shell packages, there's a built-in feature named "float" that is an alias for "typeset -E" for "typeset -i). ksh/Korn shell has "typeset -F" and "typeset -E" available, but these aren't available When using bc, 0 is false and 1 is true. Bill Parker is getting voted down, because his definitions are reversed from normal code convention. Normally, true is defined as 0 and false is defined as nonzero. 1 will work for false, as will 9999 and -1. Same with function return values - 0 is success and anything nonzero is failure.

Bash Shell: Essential Programs for Your Survival at Work: For , optional The && operator causes the shell to test the exit status of the The || control operator also causes bash to test the exit status of the first command but has the These utilities do nothing and return true (0) and false (1) exit statuses,​  All else evaluates to true. Lua has a boolean data type, but non-boolean values can also behave as booleans. The non-value nil evaluates to false, whereas every other data type always evaluates to true, regardless of value. Tcl. Tcl has no separate Boolean type. Like in C, the integers 0 (false) and 1 (true - in fact any nonzero integer) are used.

A Practical Guide to Linux Commands, Editors, and Shell Programming, A Boolean test simply checks a value to see if it's true or false. To the shell, the value 0 means true or success, and anything else means false or failure. expressions involving numbers and strings, setting its exit status to 0 (true) or 1 (​false): 0 is considered to be false, and 1 to be true, not just for C, but for most languages. This is because in binary or general computing, 1 represents ON, and 0 represents OFF. Intuitively, you could translate that to true or false, respectively. 148 views · View 3 Upvoters

Booleans and Return Codes, Read the examples shown in this Shell sequence: >>> bool(2) True >>> bool(-​3.1) True >>> bool(0) False >>> bool(0.0) False >>> bool(None) empty string ( '' , but not '0' or 'hi' or 'False') and the including empty list ( [] , but not [1,2, 3] or [0] )​.

Comments
  • It's also in line with the Unix Way... don't return anything on success.
  • Because an exit status is not a boolean. Simple as that.
  • Keep in mind that false is not a boolean, as in other programming languages. It's just a program located at /bin/false (/usr/bin/false on a Mac) that's meant to always return an error exit code 1. Similar for true. So there's no such thing as casting here. It's just all about exit codes.
  • A shell is a (user) interface to an operating system. Unix etc. programs follow the convention of exiting with 0 as OK, for the reason given in the answers (ability to communicate more than one failure reason). The shell simply keeps this convention, which makes constructs like if myprog; then echo OK; fi easy and intuitive. Otherwise you would have to invert every test for success of a program!
  • I understand this answer, but I still don't get why bool to int conversion is inverted. Is there a "return boolean convention" that says: if you return true, it means there is no errors, if you return false, it means an error occured (like the "integer = error code convention" that is more well known)?
  • Assuming there is a boolean to int conversion implies that you didn't really understand the answer. Zero means success and all of 1, 2, ..., 255 are error codes which can usefully communicate different failure scenarios. A particular example is xargs which uses different error codes in the range around 127 to indicate how a group of commands failed. The conversion which can be done is int to bool where 0 maps to success (which I guess you want to express as true / 1; but realize that this is just another arbitrary convention) and all other values to failure.
  • This pragmatic answer showing the usefulness of a variety of return codes is preferable to the preachy-ness of some of the other answers.
  • And just for the fun of it, I'll point out that /usr/include/sysexits.h notes exit values that are perhaps more aspirational, even though the convention they represent dates back to the 1980s. This convention exists outside the scope of bash.
  • A great, simple and pragmatic explanation. This needs to be at the top.
  • "If 0 was error, then the program could only present one kind of error". This statement is key and the reason why this answer should be at the top.
  • @LuisLavaire That is undefined behavior. In practice, the number tends to get truncated; but it would definitely not be "more wrong" if the runtime generated a warning and/or simply crashed. The OS reserved exactly one byte for this information and attempting to put more than one byte there is definitely an error. But the OS designers probably ran into crashes on the first day, and shrugged, and decided that the best they can do is to just truncate the value and move on.
  • Hello, Just to stress that, if the shell were interpreting zero as false and non-zero as true, the trick of doing mkdir deleteme && cd _$ && pwd would not really fail; but we would have to replace it by mkdir deleteme || cd _$ || pwd, which in my opinion is far less clear, because what we actually want to do is mkdir deleteme "and" cd _$ "and" pwd... (with "and" having here its meaning from ordinary language).
  • I think I covered that in my answer. To be clear though, when you invert the logic it is not enough to just replace the && operators with || operators. You would need to fully apply De Morgan's law. See: en.wikipedia.org/wiki/De_Morgan%27s_laws
  • Another consideration: I see at least three reasons why, on a general basis, it would be natural to state that true corresponds to zero and false corresponds to nonzero. First, if I tell you something, "having told you the truth" depends on the number of lies that I have told: either it is zero and I have told (globally) the truth, or it is nonzero and I have lied. This is essentially the same of wanting the logical and to correspond to the common "and" of addition (when restricting to natural numbers, obviously).