BASH ; || && Befehle Abbruch nach ersten Fehler

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
nudgegoonies
Beiträge: 939
Registriert: 16.02.2009 09:35:10

BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von nudgegoonies » 19.12.2023 12:26:38

Wenn ich mehrere BASH Befehle interaktiv in der Shell mit ; || und && konkateniere wird nicht nach dem ersten Exit-Code !=1 abgebrochen. Beispiel:

Code: Alles auswählen

❯ false && echo "foo" ; echo "bar"
bar
Ich hätte erwartet, dass nach dem false abgebrochen wird, aber er überspringt nur das foo und führ bar auf jeden Fall aus. Kann ich einen Abbruch nach dem ersten Fehler erzwingen, so wie bei -e in Scripten?
Soft: Bullseye AMD64, MATE Desktop. Repo's: Backports, kein Proposed, eigene Backports. Grafik: Radeon R7 360 MESA.
Hardware: Thinkstation S20, Intel X58, 16GB, Xeon W3530, BCM5755 NIC, EMU10K1 SND, SATA SSD+HDS und DVD+RW.

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von JTH » 19.12.2023 12:40:15

Dafür müsstest du die hinteren Befehle mit { … } gruppieren. Die Verknüpfung && bezieht sich dann auf der rechten Seite auf die ganze Gruppe:

Code: Alles auswählen

false && { echo "foo" ; echo "bar"; }
Wichtig: Der letzte Befehl in so einer Gruppe muss, wenn wie hier in einer Zeile geschrieben, immer mit Semikolon beendet werden. Bei anderen Konstrukten, einer Subshell ( … ) z.B., ist das nicht der Fall.
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
Livingston
Beiträge: 1455
Registriert: 04.02.2007 22:52:25
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: 127.0.0.1

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von Livingston » 19.12.2023 12:43:27

Das ";" lässt Dich nur Zeilensprünge einsparen. Du hättest Dein Beispiel also auch ohne Semikolon und in zwei Zeilen schreiben können. Eine Lösung wäre:

Code: Alles auswählen

false && echo "foo" && echo "bar"
oder

Code: Alles auswählen

false && { echo "foo"; echo "bar"; }
EDIT: JTH hat das Rennen gewonnen :wink:
Der Hauptunterschied zwischen etwas, was möglicherweise kaputtgehen könnte und etwas, was unmöglich kaputtgehen kann, besteht darin, dass sich bei allem, was unmöglich kaputtgehen kann, falls es doch kaputtgeht, normalerweise herausstellt, dass es unmöglich zerlegt oder repariert werden kann.
Douglas Adams

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von JTH » 19.12.2023 12:53:11

Livingston hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:43:27
EDIT: JTH hat das Rennen gewonnen :wink:
8)

Livingston hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:43:27
Eine Lösung wäre:

Code: Alles auswählen

false && echo "foo" && echo "bar"
Das hat allerdings noch ein leicht anderes Verhalten: Falls echo "foo" fehlschlüge, würde echo "bar" nicht mehr ausgeführt werden. In der Eingangsfrage war das etwas anders, da sollte echo "bar" unabhängig vom Erfolg von echo "foo" laufen.

Beides kann natürlich eine sinnvolle Lösung sein, je nach vorliegender Aufgabe.
Manchmal bekannt als Just (another) Terminal Hacker.

tobo
Beiträge: 1997
Registriert: 10.12.2008 10:51:41

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von tobo » 19.12.2023 12:56:03

Livingston hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:43:27
Das ";" lässt Dich nur Zeilensprünge einsparen. Du hättest Dein Beispiel also auch ohne Semikolon und in zwei Zeilen schreiben können. Eine Lösung wäre:

Code: Alles auswählen

false && echo "foo" && echo "bar"
oder

Code: Alles auswählen

false && { echo "foo"; echo "bar"; }
Wobei die beiden Beispiele aber logisch nicht identisch sind: Im 1. Beispiel wird `echo bar' nur ausgeführt, wenn `echo foo' erfolgreich war. Im 2. Beispiel wird `echo bar' immer nach einem `echo foo' ausgeführt.

Edit: Gab's hier nicht mal eine Benachrichtigung vor dem Senden eines neuen Beitrags, dass andere Beiträge in der Zwischenzeit eingeangen sind?
Zuletzt geändert von tobo am 19.12.2023 12:58:32, insgesamt 1-mal geändert.

uname
Beiträge: 12076
Registriert: 03.06.2008 09:33:02

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von uname » 19.12.2023 12:58:14

Vielleicht etwas offtopic:
Ich bin von der Logik von && und || in Bash auch immer wieder begeistert. Leider hat mein privates Umfeld überhaupt kein Interesse an der Booleschen Algebra, Venn-Diagramme oder auch an die wahrheitsfunktionale Implikation (ist hier aber auch nicht relevant).

Mein Lieblingsbeispiel für || ist im Übrigen der Terminalmultiplexer tmux
Aufruf

Code: Alles auswählen

tmux attach || tmux new 
Kurzform

Code: Alles auswählen

tmux a || tmux
So wird entweder eine Tmux-Sitzung erneut aufgerufen oder eine neue Tmux-Sitzung erzeugt. Hierdurch stellt man sicher, dass Debiantmux immer die selbe Sitzung aufruft. Ok bei Debianscreen gibt es entsprechende Parameter. Da braucht man sich die Mühe erst gar nicht machen. Aber einfach von der Logik genial. Leider kann sich mein persönliches Umfeld dafür gar nicht begeistern und verwendet Oder und exklusives Oder meistens falsch. Daher muss ich euch damit langweilen.

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von JTH » 19.12.2023 13:07:03

uname hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:58:14
Vielleicht etwas offtopic:
Ich bin von der Logik von && und || in Bash auch immer wieder begeistert. Leider hat mein privates Umfeld überhaupt kein Interesse an der Booleschen Algebra, Venn-Diagramme oder auch an die wahrheitsfunktionale Implikation (ist hier aber auch nicht relevant).
Was hier zum Tragen kommt, ist die unterschiedliche Wertigkeit der Operatoren && und ;: Operatorrangfolge (auf Englisch meist: operator precedence).

Erst wird && beachtet und die drumherum stehenden Kommandos „zusammengefasst“, anschließend das Semikolon. Was in der Eingangsfrage also effektiv steht, ist:

Code: Alles auswählen

{ false && echo "foo"; }; echo "bar"

uname hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:58:14
Kurzform

Code: Alles auswählen

tmux a || tmux
Tss, immer noch vieeeel zu lang:

Code: Alles auswählen

tmux new -A
:wink:
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
cosinus
Beiträge: 3441
Registriert: 08.02.2016 13:44:11
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Bremen

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von cosinus » 19.12.2023 13:42:02

Zur Ergänung hier noch ein paar Beispiele von stackoverflow [https://stackoverflow.com/questions/451 ... ll-command]

Code: Alles auswählen

$ false || echo "Oops, fail"
Oops, fail

$ true || echo "Will not be printed"
$  

$ true && echo "Things went well"
Things went well

$ false && echo "Will not be printed"
$

$ false ; echo "This will always run"
This will always run

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von Meillo » 19.12.2023 14:10:40

nudgegoonies hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 12:26:38
Ich hätte erwartet, dass nach dem false abgebrochen wird, aber er überspringt nur das foo und führ bar auf jeden Fall aus. Kann ich einen Abbruch nach dem ersten Fehler erzwingen, so wie bei -e in Scripten?
Ich finde, man kann die Frage in zwei Arten verstehen:

1) Wie verhindere ich, dass `bar' ausgefuehrt wird. Das habt ihr beantwortet.

2) Wie schaffe ich es, dass das Script nach `false' abbricht (wie bei `set -e')?


Zu (2) ist zu sagen, dass der Exitcode durch `&&' schon verarbeitet wird und damit `set -e' nicht mehr abbricht. Aber du kannst hinter ein `&& foo' noch ein `|| exit 1' haengen, das dann im gegenteiligen Fall ausgefuehrt wird.

Am besten, du beschreibst mal noch, was du eigentlich erreichen willst.
Use ed once in a while!

tobo
Beiträge: 1997
Registriert: 10.12.2008 10:51:41

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von tobo » 19.12.2023 20:00:33

Meillo hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 14:10:40
Aber du kannst hinter ein `&& foo' noch ein `|| exit 1' haengen, das dann im gegenteiligen Fall ausgefuehrt wird.
Nö, weil `A && B || C' kein if-then-else ist. C wird ausgeführt, wenn A oder B scheitert:

Code: Alles auswählen

$ true && false || echo FALSE
FALSE
$ false && true || echo FALSE
FALSE
$

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von Meillo » 19.12.2023 21:48:40

Stimmt. ``Gegenteilig'' ist falsch.

Immerhin macht das Konstrukt zufaellig dennoch was nudgegoonies sich vermutlich wuenscht -- Glueck gehabt! 8)
Use ed once in a while!

Benutzeravatar
Livingston
Beiträge: 1455
Registriert: 04.02.2007 22:52:25
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: 127.0.0.1

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von Livingston » 19.12.2023 22:51:25

Ich hab mir für solche Fälle angewöhnt, immer Klammern zu setzen.
Der Hauptunterschied zwischen etwas, was möglicherweise kaputtgehen könnte und etwas, was unmöglich kaputtgehen kann, besteht darin, dass sich bei allem, was unmöglich kaputtgehen kann, falls es doch kaputtgeht, normalerweise herausstellt, dass es unmöglich zerlegt oder repariert werden kann.
Douglas Adams

Benutzeravatar
cosinus
Beiträge: 3441
Registriert: 08.02.2016 13:44:11
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Bremen

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von cosinus » 19.12.2023 23:26:36

Meillo hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 21:48:40
Stimmt. ``Gegenteilig'' ist falsch.)
Hab da mal ne blöde Frage. Wieso schreibst du das ``Gegenteilig'' statt "Gegenteilig" oder 'Gegenteilig' :?:

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von Meillo » 19.12.2023 23:35:15

OT:
cosinus hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 23:26:36
Meillo hat geschrieben: ↑ zum Beitrag ↑
19.12.2023 21:48:40
Stimmt. ``Gegenteilig'' ist falsch.)
Hab da mal ne blöde Frage. Wieso schreibst du das ``Gegenteilig'' statt "Gegenteilig" oder 'Gegenteilig' :?:
... weil das aus der Geschichte kommt. In Latex, troff und insbesondere m4 werden Quotes genau so genutzt. Mit einem passenden Font, der die historische Tradition wiedergibt, sieht das auch sinnvoll aus: http://marmaro.de/rem/texte/anfuehrungszeichen.png

Und der Nebeneffekt, dass ich danach gefragt werde und dann was zur Geschichte erzaehlen kann, kommt mir auch nicht ungelegen. :P
Use ed once in a while!

Benutzeravatar
cosinus
Beiträge: 3441
Registriert: 08.02.2016 13:44:11
Lizenz eigener Beiträge: GNU General Public License
Wohnort: Bremen

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von cosinus » 19.12.2023 23:44:31

Ok, das kannte ich noch nicht obwohl ich auch schon 40 Jahre auf dieser Erde herumspaziere. Vielen Dank @Meillo :D
Edit: Aber sind wir hier bei (in?) Latex lieber Meillo? :wink:

nudgegoonies
Beiträge: 939
Registriert: 16.02.2009 09:35:10

Re: BASH ; || && Befehle Abbruch nach ersten Fehler

Beitrag von nudgegoonies » 20.12.2023 11:25:28

Vielen Dank für die vielen Antworten - Ihr seid klasse :THX:

Mein Kommando ist zu länglich und fachlich, weshalb ich das Minimalbeispiel angelegt habe.
In meinem konkreten Fall war das false ein Kommando, das nicht fehlschlagen darf. Und wenn es fehlschlägt, sollten keine anderen Kommandos mehr ausgeführt werden, damit ich debuggen kann.
Das foo war dagegen ein Kommando, das fehlschlagen darf, weil es nicht idempotent ist. Also es kein -p wie bei mkdir oder -f wie bei rm anbietet.
Und das bar war ein reboot :lol:

Und meine Verwunderung war groß, als die Fehlermeldungen von false vorbeihuschten und danach trotzdem rebooted wurde :facepalm:

Eure Antworten haben mir sehr geholfen! Besonders die implizite Klammerung explizit zu machen hilft sehr! Bei vielen Kommandos wird es, mit oder ohne Klammern, unübersichtlich. Zumindest als Einzeiler.
Soft: Bullseye AMD64, MATE Desktop. Repo's: Backports, kein Proposed, eigene Backports. Grafik: Radeon R7 360 MESA.
Hardware: Thinkstation S20, Intel X58, 16GB, Xeon W3530, BCM5755 NIC, EMU10K1 SND, SATA SSD+HDS und DVD+RW.

Antworten