为什么0在shell中是true,但是false是1?

false; echo $? 

以上将输出1 ,这与我所知道的所有其他编程语言是矛盾的。

有什么理由呢?

这是一个惯例,但是当你考虑它的时候,这是一个特别有用的惯例。 一般来说,如果一个程序成功,那就是你所需要知道的。 但是,如果它失败了,你可能需要知道关于失败的各种信息 – 为什么发生了,怎么修正等等。零意味着“成功”和非零意味着失败让你可以很容易地检查成功,如果你想要了解更多细节的特定错误。 许多API和框架都有一个类似的约定 – 成功返回0的函数和那些失败的函数返回描述特定故障情况的错误代码。

Bash是一种编程(脚本)语言,但它也是一个shell和一个用户界面。 如果0是错误的,那么程序只能出现一种错误。

然而在Bash中,任何非零值都是一个错误,我们可能使用1-255中的任何数字来表示一个错误。 这意味着我们可以有许多不同的错误。 1是一个常规错误, 126表示文件不能执行, 127表示'没有find命令'等。这里是Bash 保留退出代码列表,显示了一些最常见的退出代码。

成功的种类也很多(退出状态为0 )。 但是,成功将允许您继续下一步 – 您可以将结果打印到屏幕上,或者执行命令等。

这里有两个相关的问题。

首先,OP的问题, 为什么0是正确的,但在shell中为false? 第二, 为什么应用程序成功返回0,失败则返回非零?

要回答OP的问题,我们需要了解第二个问题。 这个post的许多答案都描述了这是一个公约,并列出了这个公约所提供的一些细节。 下面总结了其中的一些细节。

为什么应用程序成功返回0,失败则返回非零?

调用操作的代码需要知道有关操作退出状态的两件事情。 操作成功了吗? [* 1]如果操作没有成功退出,操作退出失败的原因是什么? 任何价值都可以用来表示成功。 但是0比任何其他数字更方便,因为它可以在平台之间移植。 在2011年8月16日总结xibo对这个问题的回答:

零是编码无关的。

如果我们想把一个(1)存储在一个32位的整数字中,第一个问题是“大端字还是小端字?”,接下来是“多less字节组成一个小端字? “,而零总是看起来一样。

另外需要指出的是,有些人在某个时候投了错误的字符,或者甚至是浮动的。 (int)((char)ENOLCK)当char不是至less8位长(UNIX支持7位ASCII字符机器)时不是ENOLCK,而(int)((char)0)是0字符的build筑细节。

一旦确定0将成为成功的返回值,那么使用任何非零值来表示失败是有意义的。 这允许许多退出代码来回答为什么操作失败的问题。

为什么0在shell中是true,但是false是1?

shell的基本用法之一是通过编写脚本来自动化进程。 通常这意味着调用一个操作,然后根据操作的退出状态有条件地做其他事情。 菲利普A.在他对这篇文章的回答中很好地解释说

在bash和一般的unix shell中,返回值不是布尔值。 他们是整数退出代码。

然后有必要将这些操作的退出状态解释为一个布尔值。 把一个成功的( 0 )退出状态映射到真,任何非零/失败退出状态都映射到假是有意义的。 这样做可以有条件地执行链接shell命令。

这里是一个例子mkdir deleteme && cd _$ && pwd 。 因为shell将0解释为true,所以这个命令方便地按预期工作。 如果shell将0解释为false,则必须反转每个操作的解释退出状态。

简而言之,假定应用程序返回0以表示成功退出状态,那么将shell解释为false将是无意义的。


[* 1]:是的,很多次操作需要返回的不仅仅是一个简单的成功消息,但超出了这个线程的范围。

另请参阅高级Bash脚本指南中的附录E.

这只是一个约定,0退出码意味着成功。 几乎在每个现代系统上EXIT_SUCCESS都是0。

编辑:

“为什么testing0和testing1都返回0(成功)?”

这是一个完全不同的问题。 答案是,除非该参数是空string(“”),否则传递一个testing参数总是会导致成功。 请参阅Open Group文档 。

我认为重要的一点是要理解这一点。 在bash和一般的unix shell中,返回值不是布尔值。 他们是整数退出代码。 因此,您必须根据惯例来评估它们,其中0表示成功,而其他值意味着一些错误。

使用test[ ][[ ]]运算符,在退出代码为0(/ bin / true的结果)的情况下,bash条件评估为true。 否则,他们评价为假。

string的评估与退出代码不同:

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

(( ))算术运算符将1和0解释为真和假。 但是,该运算符不能用作完全替代test[ ][[ ]] 。 下面是一个显示算术运算符有用的例子:

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

通常情况下,程序成功返回零,失败则返回非零; false返回1,因为它是一个非常方便的非零值,但是通常任何非零值意味着某种sorting失败,并且许多程序将返回不同的非零值来指示不同的失败模式

AFAIK这来自C惯例,你应该返回0,如果成功。 看到:

 man close 

大部分C(POSIX)API都是这样构build的。 http://en.wikipedia.org/wiki/C_POSIX_library

你试图把真/假与成功/失败等同起来。

他们完全是两个,虽然起初微妙,不同的二分法!

在shell脚本中,不存在true / false这样的事情。 壳'expression式'不被解释为真/假。 相反,shell的“expression式”是成功或失败的过程。

显然,一个过程可能会失败,原因很多。 因此,我们需要一个更大的集合代码来映射可能的故障。 积极的整数伎俩。 另一方面,如果这个过程成功了,那就意味着它完成了它应该做的事情。 由于只有一种方法可以做到这一点,我们只需要一个代码。 0做的伎俩。

在C中,我们正在创build一个程序。 在一个shell脚本中,我们正在运行一些程序来完成一些任务。

区别!

这是一个可以追溯到Unix早期的约定。

按照惯例,所有系统调用成功返回0,否则不为零,因为可以用不同的数字表示不同的失败原因。

壳遵循这个约定,0表示最后一个命令成功,否则非零。 类似地,非零返回值适用于输出错误消息:例如1:“脑死亡”,2:“无情”,等等。