Il y a deux problèmes liés ici.
Tout d'abord, la question du PO, pourquoi 0 est vrai mais faux est 1 dans le shell? et le second, pourquoi les applications renvoient-elles 0 pour succès et non nul pour échec?
Pour répondre à la question du PO, nous devons comprendre la deuxième question. Les nombreuses réponses à ce post ont décrit qu'il s'agit d'une convention et ont énuméré certaines des subtilités de cette convention. Certaines de ces subtilités sont résumées ci-dessous.
Pourquoi les applications renvoient-elles 0 en cas de succès et non nul en cas d'échec?
Le code qui appelle une opération doit connaître deux choses sur l'état de sortie de l'opération. L'opération s'est-elle terminée avec succès? [* 1] Et si l'opération ne se termine pas correctement, pourquoi l'opération s'est-elle terminée sans succès? N'importe quelle valeur peut être utilisée pour indiquer le succès. Mais 0 est plus pratique que tout autre nombre car il est portable entre les plates-formes. Résumant la réponse de xibo à cette question le 16 août 2011:
Le zéro est indépendant du codage.
Si nous voulions stocker un (1) dans un mot entier de 32 bits, la première question serait "mot big-endian ou petit-endian?", Suivi de "combien de temps les octets composent-ils un mot little-endian?" ", tandis que zéro aura toujours le même aspect.
De plus, il faut s'attendre à ce que certaines personnes lancent errno en char ou short à un moment donné, ou même en flottant. (int) ((char) ENOLCK) n'est pas ENOLCK lorsque char n'a pas au moins 8 bits de long (les machines à caractères ASCII 7 bits sont prises en charge par UNIX), tandis que (int) ((char) 0) vaut 0 indépendamment de détails architecturaux du char.
Une fois qu'il est déterminé que 0 sera la valeur de retour pour le succès, il est logique d'utiliser une valeur non nulle en cas d'échec. Cela permet à de nombreux codes de sortie de répondre à la question de savoir pourquoi l'opération a échoué.
Pourquoi 0 est vrai mais faux est 1 dans le shell?
L'un des usages fondamentaux des shells est d'automatiser les processus en les scriptant. Habituellement, cela signifie appeler une opération, puis faire autre chose de manière conditionnelle en fonction de l'état de sortie de l'opération. Philippe A. a bien expliqué dans sa réponse à ce post que
Dans bash et dans les shells Unix en général, les valeurs de retour ne sont pas booléennes. Ce sont des codes de sortie entiers.
Il est alors nécessaire d'interpréter l'état de sortie de ces opérations comme une valeur booléenne. Il est logique de mapper un 0
état de sortie réussi ( ) sur true et tout état de sortie non nul / échec sur false. Cela permet l'exécution conditionnelle de commandes shell chaînées.
Voici un exemple mkdir deleteme && cd $_ && pwd
. Comme le shell interprète 0 comme vrai, cette commande fonctionne comme prévu. Si le shell devait interpréter 0 comme faux, vous devrez inverser l'état de sortie interprété pour chaque opération.
En bref, il serait absurde pour le shell d'interpréter 0 comme faux étant donné la convention selon laquelle les applications renvoient 0 pour un statut de sortie réussi.
[* 1]: Oui, de nombreuses fois, les opérations doivent renvoyer plus qu'un simple message de réussite, mais cela dépasse la portée de ce thread.
Voir également l' annexe E dans le Guide de scripts Bash avancés