it-swarm.com.de

Mehrere Befehle in einer Zeile in der Shell ausführen

Angenommen, ich habe eine Datei /templates/Apple und ich möchte

  1. lege es an zwei verschiedenen Stellen und dann
  2. entfernen Sie das Original.

Also wird /templates/Apple nach /templates/used UND /templates/inuse kopiert und danach möchte ich das Original entfernen.

Ist cp der beste Weg, dies zu tun, gefolgt von rm? Oder gibt es einen besseren Weg?

Ich möchte alles in einer Zeile machen, also denke ich, dass es ungefähr so ​​aussieht:

cp /templates/Apple /templates/used | cp /templates/Apple /templates/inuse | rm /templates/Apple

Ist das die richtige Syntax?

328
John Redyns

Sie verwenden | (Pipe), um die Ausgabe eines Befehls in einen anderen Befehl umzuleiten. Was Sie suchen, ist der Operator &&, der den nächsten Befehl nur ausführt, wenn der vorherige erfolgreich war:

cp /templates/Apple /templates/used && cp /templates/Apple /templates/inuse && rm /templates/Apple

Oder

cp /templates/Apple /templates/used && mv /templates/Apple /templates/inuse

Um (nicht erschöpfend) die Befehlsoperatoren/Trennzeichen von bash zusammenzufassen:

  • | leitet die Standardausgabe (stdout) eines Befehls an die Standardeingabe eines anderen Befehls weiter. Beachten Sie, dass stderr immer noch an das Standardziel gesendet wird, unabhängig davon, was gerade passiert.
  • |&piped sowohl stdout als auch stderr eines Befehls in die Standardeingabe eines anderen. Sehr nützlich, verfügbar in Bash-Version 4 und höher.
  • && führt den rechten Befehl von && nur aus, wenn der vorherige erfolgreich war.
  • || führt den rechten Befehl von || aus, nur wenn der vorherige fehlgeschlagen ist.
  • ; führt den rechten Befehl von ; immer aus, unabhängig davon, ob der vorherige Befehl erfolgreich war oder fehlgeschlagen ist. Es sei denn, set -e wurde zuvor aufgerufen, wodurch bash bei einem Fehler fehlschlägt.
668

Warum nicht cp zu Position 1, dann mv zu Position 2. Dadurch wird das Original "entfernt".

Und nein, es ist nicht die richtige Syntax. | wird verwendet, um die Ausgabe eines Programms zu "leiten" und in eine Eingabe für das nächste Programm umzuwandeln. Was Sie wollen, ist ;, das mehrere Befehle trennt.

cp file1 file2 ; cp file1 file3 ; rm file1

Wenn Sie benötigen, dass die einzelnen Befehle erfolgreich ausgeführt werden MÜSSEN, bevor der nächste gestartet werden kann, verwenden Sie stattdessen &&:

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

Auf diese Weise wird der Befehl cp nicht ausgeführt, wenn einer der Befehle rm fehlschlägt.

70
Marc B

Beachten Sie, dass cp A B; rm A genau mv A B ist. Es ist auch schneller, da Sie die Bytes nicht wirklich kopieren müssen (vorausgesetzt, das Ziel befindet sich auf demselben Dateisystem), benennen Sie die Datei einfach um. Also willst du cp A B; mv A C

8
glenn jackman

Eine weitere Option ist die Eingabe Ctrl+VCtrl+J am Ende jedes Befehls.

Beispiel (Ersetzen Sie # durch Ctrl+VCtrl+J):

$ echo 1#
echo 2#
echo 3

Ausgabe:

1
2
3

Dadurch werden die Befehle ausgeführt, unabhängig davon, ob die vorherigen fehlgeschlagen sind.

Selben wie: echo 1; echo 2; echo 3

Wenn Sie die Ausführung fehlgeschlagener Befehle stoppen möchten, fügen Sie am Ende jeder Zeile außer der letzten && hinzu.

Beispiel (Ersetzen Sie # durch Ctrl+VCtrl+J):

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

Ausgabe:

1
failed-command: command not found

In zsh können Sie auch verwenden Alt+Enter oder Esc+Enter Anstatt von Ctrl+VCtrl+J

6
Eyal Levin

Versuche dies..

cp /templates/Apple /templates/used && cp /templates/Apple /templates/inuse && rm /templates/Apple

2
Peter

Pfeifen zu benutzen kommt mir komisch vor. Auf jeden Fall sollten Sie den logischen Bash-Operator and verwenden:

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

Wenn der Befehl cp fehlschlägt, wird der Befehl rm nicht ausgeführt.

Oder Sie können eine ausführlichere Befehlszeile mit einer for-Schleife und cmp erstellen.

1
Renaud