Syntax für eine einzeilige Bash-Endlosschleife

632

Ich habe Probleme, die richtige Kombination aus Semikolons und / oder Klammern zu finden. Ich würde das gerne tun, aber als Einzeiler von der Kommandozeile:

while [ 1 ]
do
    foo
    sleep 2
done
Brian Deacon
quelle
4
Ersetzen Sie Zeilenumbrüche durch Semikolons. Das gleiche gilt für for-Schleifen.
Tom
23
@ Tom: das funktioniert nicht immer. Nach dem Do müssen Sie den ersten Befehl haben, kein Semikolon
Stefano Borini

Antworten:

1229
while true; do foo; sleep 2; done

Übrigens, wenn Sie es an der Eingabeaufforderung als mehrzeilig eingeben (wie Sie zeigen) und dann den Verlauf mit dem Pfeil nach oben aufrufen, erhalten Sie ihn in einer einzelnen Zeile, korrekt interpunktiert.

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done
Stefano Borini
quelle
2
"Wenn Sie es an der Eingabeaufforderung als mehrzeilig eingeben (wie Sie zeigen) und dann den Verlauf mit dem Pfeil nach oben aufrufen, wird er in einer einzelnen Zeile angezeigt, die korrekt interpunktiert ist." war nicht wahr für mich.
Vincent Scheib
@ VincentScheib, cmdhistOption aktivieren, wenn Sie Bash verwenden?
Alok Singhal
Ausgezeichnet! Funktioniert perfekt unter Mavericks (Mac OS-X 10.9) und ermöglicht es mir, einen VPN am Laufen zu halten. Openconnect trennt die Verbindung nach einigen Stunden mit einem fehlerhaften Cookie-Fehler. Also habe ich den Befehl openconnect in ein Shell-Skript eingefügt, sudo su, um root zu werden, und diese cmd-Zeile verwendet: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts
169

Es ist auch möglich, den Befehl sleep im Zustand while zu verwenden. Einzeiler imho sauberer aussehen lassen.

while sleep 2; do echo thinking; done
Anssi
quelle
16
Dies ist mehr als nur eine Änderung der Syntax - es wird der Befehl nach dem Ruhezustand ausgeführt. In der vorherigen Antwort wird der Befehl sofort ausgeführt. Nur etwas zu beachten.
DanGordon
@ DanGordon while echo thinking ; do sleep 2 ; done Natürlich, wenn der Befehl [while] fehlschlägt, wird die Schleife beendet, so dass Sie müssen, while echo thinking || true ; do sleep 2 ; doneaber dann sind Sie zurück zuwhile true ; ...
Brian Carcich
69

Doppelpunkt ist immer "wahr":

while :; do foo; sleep 2; done
ajaaskel
quelle
15
Warum ist Doppelpunkt immer wahr?
Jürgen Paul
8
@Pineapple Under the Sea: Von der Bash-Manpage: (im Abschnitt SHELL BUILTIN-BEFEHLE) : [arguments] Keine Auswirkung; Der Befehl erweitert lediglich die Argumente und führt die angegebenen Umleitungen aus. Ein Null-Exit-Code wird zurückgegeben.
Adrian W
2
Diese Syntax wird empfohlen als: ist Teil der Shell selbst, dh: ist ein in die Shell eingebauter Befehl.
Avner
@analytik Also sagst du, das ist ein Plus oder ein Minus? ;-)
Brian Carcich
33

Sie können Semikolons verwenden, um Anweisungen zu trennen:

$ while [ 1 ]; do foo; sleep 2; done
Mipadi
quelle
3
Ich mag diese Antwort, weil sie erklärt, wann und warum; (Semikolon) ist erforderlich.
Herr AndreasGeo
29

Sie können auch den folgenden untilBefehl verwenden:

until ((0)); do foo; sleep 2; done

Beachten Sie, dass im Gegensatz zu while, untildie Befehle innerhalb der Schleife ausführen würden, solange die Testbedingung einen Exit-Status hat, der nicht Null ist.


Verwenden einer whileSchleife:

while read i; do foo; sleep 2; done < /dev/urandom

Verwenden einer forSchleife:

for ((;;)); do foo; sleep 2; done

Ein anderer Weg mit until:

until [ ]; do foo; sleep 2; done
devnull
quelle
Das until ((0)); do foo; sleep 2; donescheint nicht zu funktionieren. Es ist unendlich.
030
11

Eine sehr einfache Endlosschleife .. :)

while true ; do continue ; done

Für Ihre Frage wäre es:

while true; do foo ; sleep 2 ; done
Mack
quelle
8

Ich verwende die Semikolons nur für die WHILE-Anweisung und den && -Operator, damit die Schleife mehr als eine Sache tut ...

Also mache ich es immer so

while true ; do echo Launching Spaceship into orbit && sleep 5s && /usr/bin/launch-mechanism && echo Launching in T-5 && sleep 1s && echo T-4 && sleep 1s && echo T-3 && sleep 1s && echo T-2 && sleep 1s && echo T-1 && sleep 1s && echo liftoff ; done
Thomas
quelle
1
Nun, die Verwendung &&in der Schleife ist die gleiche wie zu jeder anderen Zeit, nicht wahr? Benötigen Sie das zweite, was nur passiert, wenn das erste passiert, dann reicht die Verwendung von &&else ;aus. Wirklich, Sie möchten den Inhalt dieser Schleife kurz und einfach halten, idealerweise nur einen Befehl, also eine Funktion oder ein Skript.
Thecoshman
7

Verwenden Sie watchstattdessen eine einfache Prozessüberwachung

Christian Schwarz
quelle
6

Verwenden von while:

while true; do echo 'while'; sleep 2s; done

Verwenden der forSchleife:

for ((;;)); do echo 'forloop'; sleep 2; done

Verwenden von Recursion(etwas anders als oben, Tastatur-Interrupt wird es nicht stoppen)

list(){ echo 'recursion'; sleep 2; list; } && list;
Muhammad Soliman
quelle
5

Wenn Sie möchten, dass die while-Schleife nach einer bestimmten Bedingung stoppt und Ihr fooBefehl ungleich Null zurückgibt, wenn diese Bedingung erfüllt ist, können Sie die Schleife wie folgt unterbrechen:

while foo; do echo 'sleeping...'; sleep 5; done;

Wenn der fooBefehl beispielsweise Dinge in Stapeln löscht und 1 zurückgibt, wenn nichts mehr zu löschen ist.

Dies funktioniert gut, wenn Sie ein benutzerdefiniertes Skript haben, das einen Befehl bis zu einer bestimmten Bedingung mehrmals ausführen muss. Sie schreiben das Skript, mit 1dem beendet werden soll, wenn die Bedingung erfüllt ist, und beenden das Skript, 0wenn es erneut ausgeführt werden soll.

Angenommen, Sie haben ein Python-Skript, batch_update.pydas 100 Zeilen in einer Datenbank aktualisiert und zurückgibt, 0wenn mehr zu aktualisieren sind und 1wenn keine mehr vorhanden sind. Mit dem folgenden Befehl können Sie die Zeilen 100 gleichzeitig aktualisieren, wobei zwischen den Aktualisierungen 5 Sekunden lang geschlafen wird:

while batch_update.py; do echo 'sleeping...'; sleep 5; done;
Yep_It's_Me
quelle
und wie würdest du gehen?
AK_
Sie beenden den fooBefehl mit Code, 1wenn die while-Schleife unterbrochen werden soll. Ich habe meine Antwort mit einem Beispiel aktualisiert.
Yep_It's_Me
2

Wenn ich zwei praktische Beispiele nennen kann (mit ein bisschen "Emotion").

Dies schreibt den Namen aller Dateien, die mit ".jpg" enden, in den Ordner "img":

for f in *; do if [ "${f#*.}" == 'jpg' ]; then echo $f; fi; done

Dies löscht sie:

for f in *; do if [ "${f#*.}" == 'jpg' ]; then rm -r $f; fi; done

Ich versuche nur, einen Beitrag zu leisten.

Roger
quelle
1
@JKnight - für diese Beispiele würden Sie nicht einfach tun ls -1 *.jpgundrm *.jpg
Kevin Fegan
2
Beide sind keine Endlosschleifen und keine while-Schleifen.
Marian
2

Sie können dies auch versuchen. WARNUNG: Dies sollten Sie nicht tun, aber da die Frage nach einer Endlosschleife ohne Ende fragt ... so könnten Sie es tun.

while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done
grepit
quelle
Warum würdest du das überhaupt tun?
gniourf_gniourf
2
weil Brian Deacon, der die Frage gestellt hat, wie eine Endlosschleife wollte. Es ist mehr als eine Möglichkeit, eine Katze zu häuten, die alles ist
Grepit