Esecuzione di più comandi in una riga nella shell


388

Di 'che ho un file /templates/applee voglio farlo

  1. mettilo in due posti diversi e poi
  2. rimuovere l'originale.

Quindi, /templates/appleverrà copiato in /templates/usedAND /templates/inuse e poi mi piacerebbe rimuovere l'originale.

È cpil modo migliore per farlo, seguito da rm? O c'è un modo migliore?

Voglio fare tutto in una riga, quindi sto pensando che sarebbe simile a:

cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple

È questa la sintassi corretta?

Risposte:


792

Si sta utilizzando |(pipe) per indirizzare l'output di un comando in un altro comando. Quello che stai cercando è l' &&operatore che esegue il comando successivo solo se il precedente ha avuto esito positivo:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

O

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse

Per riassumere (non esaustivamente) gli operatori / i separatori dei comandi di bash:

  • |pipe (pipeline) l'output standard ( stdout) di un comando nell'input standard di un altro. Nota che stderrva ancora nella sua destinazione predefinita, qualunque cosa accada.
  • |&pipe entrambi stdoute stderrdi un comando nell'input standard di un altro. Molto utile, disponibile nella versione bash 4 e successive.
  • &&esegue il comando a destra &&solo se il precedente ha avuto esito positivo.
  • ||esegue il comando a destra ||solo di quello precedente fallito.
  • ;esegue il comando a destra di ;sempre, indipendentemente dal fatto che il comando precedente abbia avuto esito positivo o negativo. A meno che non sia set -estato precedentemente invocato, il che provoca bashun errore in caso di errore.

6
Upvoted. Documentazione ufficiale gnu.org/software/bash/manual/bash.html#Lists
flow2k

78

Perché non cpalla posizione 1, quindi mvalla posizione 2. Questo si occupa di "rimuovere" l'originale.

E no, non è la sintassi corretta. |viene utilizzato per "convogliare" l'output da un programma e trasformarlo in input per il programma successivo. Quello che vuoi è ;, che separa più comandi.

cp file1 file2 ; cp file1 file3 ; rm file1

Se si richiede che i singoli comandi DEVONO avere esito positivo prima di poter avviare il successivo, utilizzare &&invece:

cp file1 file2 && cp file1 file3 && rm file1

In questo modo, se uno dei cpcomandi fallisce, rmnon verrà eseguito.


10

Si noti che cp A B; rm Aè esattamente mv A B. Sarà anche più veloce, poiché non è necessario copiare effettivamente i byte (supponendo che la destinazione sia sullo stesso filesystem), basta rinominare il file. Quindi tu vuoicp A B; mv A C


7

Un'altra opzione è digitare Ctrl+V Ctrl+Jalla fine di ogni comando.

Esempio (sostituire #con Ctrl+V Ctrl+J):

$ echo 1#
echo 2#
echo 3

Produzione:

1
2
3

Questo eseguirà i comandi indipendentemente dal fatto che quelli precedenti non siano riusciti.

Uguale a: echo 1; echo 2; echo 3

Se si desidera interrompere l'esecuzione in caso di comandi non riusciti, aggiungere &&alla fine di ogni riga tranne l'ultima.

Esempio (sostituire #con Ctrl+V Ctrl+J):

$ echo 1 &&#
failed-command &&#
echo 2

Produzione:

1
failed-command: command not found

In zshpuoi anche usare Alt+Entero Esc+Enterinvece diCtrl+V Ctrl+J


3

Prova questo..

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple


2

L'uso delle pipe mi sembra strano. Ad ogni modo dovresti usare l' andoperatore logico di Bash:

$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples

Se i cpcomandi falliscono, rmnon verranno eseguiti.

Oppure, puoi creare una riga di comando più elaborata usando un forciclo e cmp.

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.