Sintaxis para un Bash infinito while de una sola línea


636

Tengo problemas para encontrar la combinación correcta de punto y coma y / o llaves. Me gustaría hacer esto, pero como una línea desde la línea de comandos:

while [ 1 ]
do
    foo
    sleep 2
done

44
reemplace las líneas nuevas con punto y coma. Lo mismo funciona para los bucles.
Tom

23
@ Tom: eso no siempre funciona. después de hacer, debe tener el primer comando, no un punto y coma
Stefano Borini

Respuestas:


1233
while true; do foo; sleep 2; done

Por cierto, si lo escribe como una línea múltiple (como se muestra) en el símbolo del sistema y luego llama al historial con la flecha hacia arriba, lo obtendrá en una sola línea, puntuada correctamente.

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

2
"si lo escribe como una línea múltiple (como se muestra) en el símbolo del sistema y luego llama al historial con la flecha hacia arriba, lo obtendrá en una sola línea, correctamente puntuado". No fue cierto para mí.
Vincent Scheib el

@ VincentScheib, marque la cmdhistopción si está usando bash?
Alok Singhal

¡Excelente! Funciona perfectamente en Mavericks (Mac OS-X 10.9) y me permite mantener una VPN en ejecución. Openconnect se desconecta después de unas horas con un error de cookie incorrecto. Así que puse el comando openconnect en un script de shell, sudo su para convertirse en root, y uso esta línea cmd: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts

170

También es posible usar el comando dormir en la condición de while. Hacer que una línea se vea más limpia en mi humilde opinión.

while sleep 2; do echo thinking; done

16
Bueno, esto hace más que solo cambiar la sintaxis: ejecutará el comando después de la suspensión. En la respuesta anterior, el comando se ejecuta de inmediato. Solo algo a tener en cuenta.
DanGordon

@DanGordon while echo thinking ; do sleep 2 ; done Por supuesto, si el comando [while] falla, el ciclo se cierra, por lo que tendría que hacerlo, while echo thinking || true ; do sleep 2 ; donepero luego volverá awhile true ; ...
Brian Carcich

69

Colón siempre es "verdadero":

while :; do foo; sleep 2; done

15
¿Por qué el colon es siempre cierto?
Jürgen Paul

8
@Pineapple Under the Sea: desde la página de manual de bash: (en la sección SHELL BUILTIN COMMANDS) : [arguments] Sin efecto; el comando no hace nada más que expandir argumentos y realizar cualquier redirección especificada. Se devuelve un código de salida cero.
Adrian W

2
esta sintaxis se recomienda como: es parte del propio shell, es decir: es un comando incorporado del shell.
avner

@analytik, entonces, ¿estás diciendo que es un más o un menos? ;-)
Brian Carcich

33

Puede usar punto y coma para separar las declaraciones:

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

3
Me gusta esta respuesta porque explica cuándo y por qué; (punto y coma) es obligatorio.
Sr. AndreasGeo

29

También puede hacer uso del untilcomando:

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

Tenga en cuenta que, en contraste con while, untilejecutaría los comandos dentro del bucle siempre que la condición de prueba tenga un estado de salida que no sea cero.


Usando un whilebucle:

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

Usando un forbucle:

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

Otra forma de usar until:

until [ ]; do foo; sleep 2; done

El until ((0)); do foo; sleep 2; doneno parece funcionar. Es continuo infinito.
030

11

Un bucle infinito muy simple .. :)

while true ; do continue ; done

Fr su pregunta sería:

while true; do foo ; sleep 2 ; done

8

Me gusta usar los puntos y comas solo para la instrucción WHILE, y el operador && para hacer que el ciclo haga más de una cosa ...

Así que siempre lo hago así

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
Bueno, el uso de &&in the loop es el mismo que en cualquier otro momento, ¿verdad? ¿Necesita la segunda cosa que suceda sólo si el primer pase, a continuación, utilizar &&lo demás ;es suficiente. Realmente, desea mantener el contenido de ese ciclo corto y simple, idealmente solo un comando, una función o un script.
thecoshman


6

Utilizando while:

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

Usando forLoop:

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

Usar Recursion, (un poco diferente al anterior, la interrupción del teclado no lo detendrá)

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

5

Si desea que el ciclo while se detenga después de alguna condición, y su foocomando devuelve un valor distinto de cero cuando se cumple esta condición, puede hacer que el ciclo se rompa así:

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

Por ejemplo, si el foocomando está eliminando cosas en lotes, y devuelve 1 cuando no queda nada para eliminar.

Esto funciona bien si tiene un script personalizado que necesita ejecutar un comando muchas veces hasta que se presente alguna condición. Usted escribe el script para salir 1cuando se cumple la condición y salir 0cuando se debe ejecutar nuevamente.

Por ejemplo, supongamos que tiene un script de Python batch_update.pyque actualiza 100 filas en una base de datos y devuelve 0si hay más para actualizar y 1si no hay más. El siguiente comando le permitirá actualizar las filas 100 a la vez con dormir durante 5 segundos entre actualizaciones:

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

y como saldrias
AK_

Hace que el foocomando salga con código 1cuando desea que se rompa el bucle while. He actualizado mi respuesta con un ejemplo.
Sip_It's_Me

2

Si puedo dar dos ejemplos prácticos (con un poco de "emoción").

Esto escribe el nombre de todos los archivos terminados con ".jpg" en la carpeta "img":

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

Esto los elimina:

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

Solo trato de contribuir.


1
@JKnight - para estos ejemplos, ¿no le acaba de hacer ls -1 *.jpgyrm *.jpg
Kevin Fegan

2
Ambos no son bucles infinitos ni bucles while.
Marian

2

También puede probar esto ADVERTENCIA: esto no debe hacerlo, pero dado que la pregunta es un bucle infinito sin fin ... así es como podría hacerlo.

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

¿Por qué harías eso?
gniourf_gniourf

2
porque Brian Deacon, que publicó la pregunta, quería un bucle infinito. Es más que una forma de desollar a un gato, eso es todo
grepit
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.