Quale è meglio: usando; o && per eseguire più comandi in una riga?


428

Nelle esercitazioni e nei tutorial vedo spesso i comandi combinati. Per esempio,

sudo apt-get update && sudo apt-get install pyrenamer

Sembra che ci siano quattro possibili connettori: &, &&, ||e ;. Sebbene il & connettore sia chiaro per me (invia un processo in background e lascia disponibile il terminale), non è chiaro quale sia la differenza tra &&e ;. E non lo sapevo ||fino al commento di Kaya.

Le seguenti domande riguardano la differenza tra i due connettori, ma lo fanno principalmente nei commenti:

Quindi, ecco una serie di domande correlate:

  1. Qual è la differenza tra ;e &&?
  2. Quando dovresti usarli rispettivamente? Sarebbe bello vedere alcuni casi d'uso: se voglio eseguire un comando e dopo averlo spento il mio computer, quale connettore dovrei scegliere?
  3. Quali sono i loro vantaggi e pericoli ? Robie Basak menziona in un commento a questa risposta che un comando simile cd /somewhere_else; rm -Rf *può avere conseguenze distruttive se il primo elemento nella catena di comando fallisce, per esempio.
  4. Se pertinente, da dove vengono?

7
C'è un altro connettore che potresti non aver incontrato: ||è lo stesso &&tranne per il fatto che esegue il secondo comando solo se il primo è uscito con uno stato diverso da zero (non riuscito).
Kaya,

4
Si noti inoltre che l'esecuzione dello script con set -einterromperà lo script in caso di errore come se tutti i comandi fossero connessi &&.
Choroba,


3
Nessuno ha risposto a Qn 4 ... Sospetto il comportamento di && e || è stato ispirato dal linguaggio di programmazione C. Nel caso di (x && y), se x viene valutato come falso, l'intera espressione deve essere falsa in modo che un compilatore possa ottimizzare la valutazione di y, nel caso in cui fosse costoso. I moderni standard C e C ++ richiedono effettivamente questa ottimizzazione, quindi i programmi possono tranquillamente supporre che y non verrà valutato se x è falso. Ad esempio, (ptr && ptr-> giorni> 31) non andrà in crash anche se ptr è nullo. Anche in C, le dichiarazioni terminano con; indipendentemente dal fatto che ci sia o meno un'altra affermazione sulla stessa riga.
Kevin,

Risposte:


772

Cheatsheet:

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.

19
E ovviamente A & B &: Esegui A in background, quindi esegui B in background (indipendentemente dal successo) e restituisci il controllo alla shell. Questo spesso funziona allo stesso modo dell'esecuzione di entrambi i processi contemporaneamente.
Espiazione limitata il

4
è possibile dire: eseguire a in background, seguito da b in background solo se ha funzionato? (Suppongo che &&&?)
user230910

15
@ user230910: sarebbe (A && B) &.
lasciato il

5
Puoi fare riferimento a questo documento autorevole per questo ?.
Jaime Hablutzel,

@Jack Quando eseguito da Cronjob, non segue del tutto questa regola, hai idea del perché? Per un file Python
CodeGuru,

77

&&esegue il secondo comando solo se il primo è uscito con stato 0 (ha avuto esito positivo). ;esegue entrambi i comandi, anche se il primo esce con uno stato diverso da zero.

Il tuo esempio con &&può essere equivalentemente parafrasato come

if sudo apt-get update ; then
    sudo apt-get install pyrenamer
fi

Grazie. Ho aggiornato la domanda per assicurarmi che le diverse domande siano facilmente distinguibili.
don.joey,

5
@Privato: dovresti usare ;se il secondo comando non ha bisogno del precedente per avere successo.
Choroba,

31

L'uso ;eseguirà i comandi indipendentemente dal fatto che il primo comando abbia esito positivo o meno.

utilizzando &&esegui il secondo comando solo quando il primo comando è stato eseguito correttamente (stato 0).

Entrambi sono usati in prospettiva diversa. Come per un processo più lungo, supponiamo che per un'installazione sia necessario compilarlo e installarlo. dovresti make && make install. Quindi l'installazione verrà eseguita solo se eseguita makecorrettamente.

Quindi per i comandi dipendenti dovresti usare &&

Scrivere bash o usare comandi con comandi indipendenti ;

Quindi, se si desidera arrestare il computer anche se il primo lavoro non è riuscito ;, ma se si desidera il completo successo del primo lavoro, avviare l'arresto&&


14

a ; bverrà eseguito b indipendentemente dallo stato di uscita di a. a && bverrà eseguito b solo se riuscito.

Ciò è necessario e sufficiente per rispondere alle prime 3 domande. In particolare, il 2 è troppo ampio e non può essere data una "sola" risposta definitiva: la soluzione migliore è decidere caso per caso.

Per quanto riguarda la quarta domanda: sono la sintassi di Bash .

Non vi è alcun pericolo intrinseco nell'uso di entrambi. Ancora una volta, la definizione sopra è sufficiente. Implica che scriverai &&quando bha effetti indesiderati se anon ci riesce. Non sono necessarie ulteriori regole o spiegazioni, IMHO.


1

UN; B # Esegui A e poi B, indipendentemente dal successo di A

A && B # Esegui B se e solo se A ha avuto successo

A || B # Esegui B se e solo se A fallito

A & # Esegui A in background.

Un'ottima regola empirica. Aggiungo che in alcuni casi, l'uso di questi comandi in una subshell ha senso quando vogliamo considerarli come una singola unità o non vogliamo accoppiare alcuni risultati delle operazioni con la shell corrente.

Esempi:

-concatena l'output di due comandi:

(ls foo; ls bar) > single-result.txt

-entrarsi in una directory ed eseguire un comando da lì senza cambiare la directory corrente della shell:

(cd target-directory && jar -xf ../my-jar)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.