Składnia dla jednowierszowej pętli Bash nieskończonej podczas pętli

633

Mam problem z wymyśleniem odpowiedniej kombinacji średników i / lub nawiasów klamrowych. Chciałbym to zrobić, ale jako jeden wiersz z wiersza poleceń:

while [ 1 ]
do
    foo
    sleep 2
done
Brian Deacon
źródło
4
zamień znaki nowej linii na średniki. To samo działa dla pętli.
Tom
23
@Tom: to nie zawsze działa. po zakończeniu musisz mieć pierwsze polecenie, a nie średnik
Stefano Borini,

Odpowiedzi:

1230
while true; do foo; sleep 2; done

Nawiasem mówiąc, jeśli wpiszesz go jako multilinię (jak pokazano) w wierszu polecenia, a następnie wywołasz historię ze strzałką w górę, otrzymasz ją w jednym wierszu, poprawnie interpunkcyjnym.

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done
Stefano Borini
źródło
2
„jeśli wpiszesz go jako multilinię (jak pokazano) w wierszu polecenia, a następnie wywołasz historię ze strzałką w górę, otrzymasz ją w jednym wierszu, poprawnie interpunkcyjnym.” nie było dla mnie prawdą.
Vincent Scheib
@VincentScheib, zaznacz cmdhistopcję, jeśli używasz bash?
Alok Singhal
Świetny! Działa doskonale na Mavericks (Mac OS-X 10.9) i pozwala mi utrzymać działanie VPN. Openconnect rozłącza się po kilku godzinach z błędem błędnego pliku cookie. Więc umieściłem polecenie openconnect w skrypcie powłoki, sudo su, aby zostać rootem, i używam tej linii cmd: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts
170

Możliwe jest również użycie polecenia uśpienia w stanie while. Sprawiając, że jednopowłokowy wygląda bardziej czysty imho.

while sleep 2; do echo thinking; done
Anssi
źródło
16
Cóż, to coś więcej niż tylko zmiana składni - wykona polecenie po uśpieniu. W poprzedniej odpowiedzi polecenie zostało wykonane natychmiast. Po prostu coś do odnotowania.
DanGordon
@DanGordon while echo thinking ; do sleep 2 ; done Oczywiście, jeśli polecenie [while] nie powiedzie się, pętla zostanie zamknięta, więc musisz, while echo thinking || true ; do sleep 2 ; doneale wrócisz dowhile true ; ...
Brian Carcich,
69

Dwukropek jest zawsze „prawdziwy”:

while :; do foo; sleep 2; done
ajaaskel
źródło
15
dlaczego dwukropek jest zawsze prawdziwy?
Jürgen Paul,
8
@Pineapple Under the Sea: Ze strony podręcznika użytkownika bash: (w sekcji KOMENDY WBUDOWANE) : [arguments] Bez efektu; polecenie nie robi nic poza rozszerzaniem argumentów i wykonywaniem określonych przekierowań. Zwracany jest zerowy kod wyjścia.
Adrian W
2
ta składnia jest zalecana, ponieważ: jest częścią samej powłoki, tzn .: jest wbudowanym poleceniem powłoki.
avner
@analytik, więc mówisz, że to plus lub minus? ;-)
Brian Carcich
33

Możesz użyć średników do oddzielenia instrukcji:

$ while [ 1 ]; do foo; sleep 2; done
mipadi
źródło
3
Podoba mi się ta odpowiedź, ponieważ wyjaśnia, kiedy i dlaczego; (średnik) jest wymagany.
Pan AndreasGeo
29

Możesz także użyć untilpolecenia:

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

Zauważ, że w przeciwieństwie do while, untilwykonywałby polecenia wewnątrz pętli, o ile warunek testowy ma status wyjścia, który nie jest równy zero.


Za pomocą whilepętli:

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

Za pomocą forpętli:

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

Innym sposobem jest użycie until:

until [ ]; do foo; sleep 2; done
diabelnie
źródło
To until ((0)); do foo; sleep 2; donenie wydaje się działać. Ciągły nieskończony.
030
11

Bardzo prosta nieskończona pętla .. :)

while true ; do continue ; done

Fr twoje pytanie brzmiałoby:

while true; do foo ; sleep 2 ; done
Mack
źródło
8

Lubię używać średników tylko do instrukcji WHILE, a operator && sprawia, że ​​pętla robi więcej niż jedną rzecz ...

Więc zawsze tak to robię

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
Tomasz
źródło
1
Cóż, użycie &&pętli jest takie samo jak w każdym innym przypadku, prawda? Czy potrzebujesz, aby druga rzecz się wydarzyła tylko wtedy, gdy pierwsza się zdarzy, to użyj &&innego ;. Naprawdę chcesz, aby zawartość tej pętli była krótka i prosta, najlepiej tylko jedno polecenie, a więc funkcja lub skrypt.
thecoshman
7

watchZamiast tego użyj prostego oglądania procesu

Christian Schwarz
źródło
6

Używanie while:

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

Korzystanie z forpętli:

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

Korzystanie Recursion, (nieco inaczej niż powyżej, przerwanie klawiatury nie zatrzyma tego)

list(){ echo 'recursion'; sleep 2; list; } && list;
Muhammad Soliman
źródło
5

Jeśli chcesz, aby pętla while zatrzymała się po spełnieniu pewnego warunku, a twoje foopolecenie zwraca wartość niezerową po spełnieniu tego warunku, możesz uzyskać przerwanie pętli w następujący sposób:

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

Na przykład, jeśli foopolecenie usuwa rzeczy partiami, a zwraca 1, gdy nie ma już nic do usunięcia.

Działa to dobrze, jeśli masz niestandardowy skrypt, który musi uruchamiać polecenie wiele razy, aż do spełnienia określonych warunków. Piszemy skrypt, aby zakończyć, 1gdy warunek jest spełniony, i zakończyć, 0kiedy powinien zostać uruchomiony ponownie.

Załóżmy na przykład, że masz skrypt w języku Python, batch_update.pyktóry aktualizuje 100 wierszy w bazie danych i zwraca, 0jeśli jest więcej do zaktualizowania, a 1jeśli ich nie ma. Następujące polecenie pozwoli ci aktualizować wiersze 100 jednocześnie z uśpieniem przez 5 sekund między aktualizacjami:

while batch_update.py; do echo 'sleeping...'; sleep 5; done;
Tak, to ja
źródło
i jak byś wyszedł?
AK_
Państwo dokonać foowyjście polecenia z kodem 1kiedy chcesz pętli while do złamania. Zaktualizowałem swoją odpowiedź za pomocą przykładu.
Yep_It's_Me
2

Czy mogę podać dwa praktyczne przykłady (z odrobiną „emocji”).

Spowoduje to zapisanie nazwy wszystkich plików zakończonych „.jpg” w folderze „img”:

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

Spowoduje to ich usunięcie:

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

Próbuję tylko pomóc.

zrozumiałem
źródło
1
@JKnight - dla tych przykładów nie zrobiłbyś ls -1 *.jpgirm *.jpg
Kevin Fegan
2
Oba nie są nieskończonymi pętlami i nie są pętlami while.
Marian
2

Możesz także tego spróbować OSTRZEŻENIE: nie powinieneś tego robić, ale ponieważ pytanie dotyczy nieskończonej pętli bez końca ... tak możesz to zrobić.

while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done
grepit
źródło
Dlaczego miałbyś to zrobić?
gniourf_gniourf
2
ponieważ Brian Deacon, który opublikował pytanie, chciał jak nieskończona pętla. To więcej niż jeden sposób na
skórowanie