Sintassi per un ciclo Bash infinito a riga singola


636

Ho problemi a trovare la giusta combinazione di punti e virgola e / o parentesi graffe. Mi piacerebbe farlo, ma come una riga dalla riga di comando:

while [ 1 ]
do
    foo
    sleep 2
done

4
sostituire le nuove righe con punti e virgola. Lo stesso vale per i loop.
Tom,

23
@ Tom: non sempre funziona. dopo il do, devi avere il primo comando, non un punto e virgola
Stefano Borini il

Risposte:


1233
while true; do foo; sleep 2; done

A proposito, se lo digiti come una multilinea (come stai mostrando) al prompt dei comandi e poi chiami la cronologia con la freccia su, la otterrai su una singola riga, correttamente punteggiata.

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done

2
"se lo digiti come multilinea (come stai mostrando) al prompt dei comandi e poi chiami la cronologia con la freccia su, la otterrai su una sola riga, correttamente punteggiata." non era vero per me.
Vincent Scheib,

@VincentScheib, seleziona l' cmdhistopzione se stai usando bash?
Alok Singhal

Eccellente! Funziona perfettamente su Mavericks (Mac OS-X 10.9) e mi consente di mantenere in esecuzione una VPN. Openconnect si disconnette dopo alcune ore con un errore cookie errato. Quindi ho inserito il comando openconnect in uno script di shell, sudo su per diventare root e utilizzo questa riga cmd: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts

170

È anche possibile utilizzare il comando sleep nelle condizioni while. Rendere l'imho di un solo aspetto più pulito.

while sleep 2; do echo thinking; done

16
Bene, questo non si limita a cambiare la sintassi: eseguirà il comando dopo la sospensione. Nella risposta precedente, il comando viene eseguito immediatamente. Solo qualcosa da notare.
DanGordon,

@DanGordon while echo thinking ; do sleep 2 ; done Naturalmente se il comando [while] fallisce, il ciclo termina, quindi dovresti, while echo thinking || true ; do sleep 2 ; donema poi torni awhile true ; ...
Brian Carcich,

69

I due punti sono sempre "veri":

while :; do foo; sleep 2; done

15
perché il colon è sempre vero?
Jürgen Paul,

8
@Pineapple Under the Sea: Dalla pagina man bash: (nella sezione SHELL BUILTIN COMMANDS) : [arguments] Nessun effetto; il comando non fa altro che espandere gli argomenti ed eseguire i reindirizzamenti specificati. Viene restituito un codice di uscita zero.
Adrian W,

2
questa sintassi è raccomandata come: fa parte della shell stessa, cioè: è un comando incorporato della shell.
Avner

@analytik, quindi stai dicendo che è un vantaggio o un difetto? ;-)
Brian Carcich,

33

È possibile utilizzare i punti e virgola per separare le istruzioni:

$ while [ 1 ]; do foo; sleep 2; done

3
Mi piace questa risposta perché spiega quando e perché; (punto e virgola) è obbligatorio.
Mr. AndreasGeo,

29

Puoi anche usare il untilcomando:

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

Si noti che, al contrario di while, untileseguirà i comandi all'interno del loop purché la condizione di test abbia uno stato di uscita diverso da zero.


Utilizzando un whileloop:

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

Utilizzando un forloop:

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

Un altro modo usando until:

until [ ]; do foo; sleep 2; done

Il until ((0)); do foo; sleep 2; donenon sembra al lavoro. È infinito continuo.
030,

11

Un ciclo infinito molto semplice .. :)

while true ; do continue ; done

La tua domanda sarebbe:

while true; do foo ; sleep 2 ; done

8

Mi piace usare i punti e virgola solo per l'istruzione WHILE e l'operatore && per fare in modo che il ciclo faccia più di una cosa ...

Quindi lo faccio sempre così

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

1
Bene, l'uso di &&in the loop è lo stesso di qualsiasi altra volta, non è vero. Hai bisogno che accada la seconda cosa solo se accade la prima, quindi basta usare &&altro ;. Davvero, vuoi mantenere i contenuti di quel ciclo brevi e semplici, idealmente solo un comando, quindi una funzione o uno script.
thecoshman,


6

Utilizzando while:

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

Utilizzando forLoop:

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

Usando Recursion, (un po 'diverso da quello sopra, l'interrupt della tastiera non lo fermerà)

list(){ echo 'recursion'; sleep 2; list; } && list;

5

Se vuoi che il ciclo while si fermi dopo una certa condizione e il tuo foocomando restituisce un valore diverso da zero quando questa condizione è soddisfatta, puoi interrompere il ciclo in questo modo:

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

Ad esempio, se il foocomando sta eliminando elementi in batch e restituisce 1 quando non è rimasto nulla da eliminare.

Funziona bene se si dispone di uno script personalizzato che deve eseguire un comando più volte fino a quando non si verifica una condizione. Si scrive lo script con 1cui uscire quando viene soddisfatta la condizione e si esce con 0quando deve essere eseguito nuovamente.

Ad esempio, supponiamo di avere uno script Python batch_update.pyche aggiorna 100 righe in un database e restituisce 0se ce ne sono altre da aggiornare e 1se non ce ne sono più. Il seguente comando ti consentirà di aggiornare le righe 100 alla volta con sospensione per 5 secondi tra gli aggiornamenti:

while batch_update.py; do echo 'sleeping...'; sleep 5; done;

e come usciresti?
AK_17

Fai foouscire il comando con il codice 1quando vuoi che il ciclo while si interrompa. Ho aggiornato la mia risposta con un esempio.
Yep_It's_Me

2

Se posso fare due esempi pratici (con un po 'di "emozione").

Questo scrive il nome di tutti i file terminati con ".jpg" nella cartella "img":

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

Questo li cancella:

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

Sto solo cercando di contribuire.


1
@JKnight - per questi esempi, non lo faresti ls -1 *.jpgerm *.jpg
Kevin Fegan,

2
Entrambi non sono loop infiniti e non mentre loop.
Marian,

2

Puoi provare anche questo ATTENZIONE: questo non dovresti farlo ma poiché la domanda richiede un ciclo infinito senza fine ... ecco come potresti farlo.

while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done

Perché dovresti farlo?
gniourf_gniourf

2
perché Brian Deacon, che ha pubblicato la domanda, voleva un loop infinito. È più di un modo per
scuoiare
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.