Ci sono due problemi correlati qui.
In primo luogo, la domanda dell'OP, perché 0 è vero ma falso è 1 nella shell? e il secondo, perché le applicazioni restituiscono 0 per il successo e diverso da zero per il fallimento?
Per rispondere alla domanda del PO dobbiamo capire la seconda domanda. Le numerose risposte a questo post hanno descritto che questa è una convenzione e hanno elencato alcune delle sottigliezze che questa convenzione offre. Alcune di queste sottigliezze sono riassunte di seguito.
Perché le applicazioni restituiscono 0 per il successo e diverso da zero per il fallimento?
Il codice che richiama un'operazione deve conoscere due cose sullo stato di uscita dell'operazione. L'operazione è terminata con successo? [* 1] E se l'operazione non è terminata correttamente, perché l'operazione è terminata senza successo? Qualsiasi valore potrebbe essere utilizzato per indicare il successo. Ma 0 è più conveniente di qualsiasi altro numero perché è portabile tra le piattaforme. Riassumendo la risposta di xibo a questa domanda il 16 agosto 2011:
Zero è indipendente dalla codifica.
Se volessimo memorizzare uno (1) in una parola intera a 32 bit, la prima domanda sarebbe "parola big-endian o parola little-endian?", Seguita da "quanto tempo sono i byte che compongono una parola little-endian?" ", mentre lo zero sarà sempre lo stesso.
Inoltre ci si deve aspettare che alcune persone lanciano errno a char o short ad un certo punto, o anche a float. (int) ((char) ENOLCK) non è ENOLCK quando char non è lungo almeno 8 bit (le macchine con caratteri ASCII a 7 bit sono supportate da UNIX), mentre (int) ((char) 0) è 0 indipendente dal dettagli architettonici di char.
Una volta stabilito che 0 sarà il valore restituito per il successo, ha senso utilizzare qualsiasi valore diverso da zero per il fallimento. Ciò consente a molti codici di uscita di rispondere alla domanda sul perché l'operazione non è riuscita.
Perché 0 è vero ma falso è 1 nella shell?
Uno degli usi fondamentali delle shell è automatizzare i processi tramite script. Di solito questo significa invocare un'operazione e quindi fare qualcos'altro in base allo stato di uscita dell'operazione. Philippe A. ha spiegato bene nella sua risposta a questo post che
In bash e nelle shell unix in generale, i valori restituiti non sono booleani. Sono codici di uscita interi.
È quindi necessario interpretare lo stato di uscita di queste operazioni come un valore booleano. Ha senso mappare uno 0
stato di uscita riuscito ( ) a vero e qualsiasi stato di uscita diverso da zero / errore a falso. Ciò consente l'esecuzione condizionale dei comandi di shell concatenati.
Ecco un esempio mkdir deleteme && cd $_ && pwd
. Poiché la shell interpreta 0 come vero, questo comando funziona convenientemente come previsto. Se la shell dovesse interpretare 0 come falso, dovresti invertire lo stato di uscita interpretato per ogni operazione.
In breve, non avrebbe senso che la shell interpretasse 0 come falso, data la convenzione secondo cui le applicazioni restituiscono 0 per uno stato di uscita riuscito.
[* 1]: Sì, molte volte le operazioni devono restituire più di un semplice messaggio di successo, ma questo va oltre lo scopo di questo thread.
Vedi anche l' Appendice E nella Advanced Bash-Scripting Guide