Syntaxe d'une boucle Bash infinie sur une seule ligne

636

J'ai du mal à trouver la bonne combinaison de points-virgules et / ou d'accolades. Je voudrais le faire, mais en tant que ligne unique à partir de la ligne de commande:

while [ 1 ]
do
    foo
    sleep 2
done
Brian Deacon
la source
4
remplacer les retours à la ligne par des points-virgules. Il en va de même pour les boucles for.
Tom
23
@Tom: ça ne marche pas toujours. après le do, vous devez avoir la première commande, pas un point
Stefano Borini

Réponses:

1233
while true; do foo; sleep 2; done

Soit dit en passant, si vous le tapez sous forme de multiligne (comme vous le montrez) à l'invite de commandes, puis appelez l'historique avec la flèche vers le haut, vous l'obtiendrez sur une seule ligne, correctement ponctuée.

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done
Stefano Borini
la source
2
"Si vous le tapez sous forme de multiligne (comme vous le montrez) à l'invite de commande, puis appelez l'historique avec la flèche vers le haut, vous l'aurez sur une seule ligne, correctement ponctuée." n'était pas vrai pour moi.
Vincent Scheib
@VincentScheib, cochez l' cmdhistoption si vous utilisez bash?
Alok Singhal
Excellent! Fonctionne parfaitement sur Mavericks (Mac OS-X 10.9) et me permet de garder un vpn en marche. Openconnect se déconnecte après quelques heures avec une erreur de cookie incorrecte. J'ai donc mis la commande openconnect dans un script shell, sudo su pour devenir root, et j'utilise cette ligne cmd: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts
170

Il est également possible d'utiliser la commande sleep dans l'état while. Rendre une doublure plus propre à mon humble avis.

while sleep 2; do echo thinking; done
Anssi
la source
16
Eh bien, cela fait plus que simplement changer la syntaxe - il exécutera la commande après le sommeil. Dans la réponse précédente, la commande est exécutée immédiatement. Juste quelque chose à noter.
DanGordon
@DanGordon while echo thinking ; do sleep 2 ; done Bien sûr, si la commande [while] échoue, la boucle se termine, vous devriez donc le faire, while echo thinking || true ; do sleep 2 ; donemais vous revenez àwhile true ; ...
Brian Carcich
69

Le colon est toujours "vrai":

while :; do foo; sleep 2; done
ajaaskel
la source
15
pourquoi le côlon est-il toujours vrai?
Jürgen Paul
8
@Pineapple Under the Sea: depuis la page de manuel bash: (dans la section SHELL BUILTIN COMMANDS) : [arguments] Aucun effet; la commande ne fait rien d'autre que d'étendre les arguments et d'effectuer les redirections spécifiées. Un code de sortie zéro est renvoyé.
Adrian W
2
cette syntaxe est recommandée car: fait partie du shell lui-même, c'est-à-dire: est une commande intégrée au shell.
avner
@analytik alors dites-vous que c'est un plus ou un moins? ;-)
Brian Carcich
33

Vous pouvez utiliser des points-virgules pour séparer les instructions:

$ while [ 1 ]; do foo; sleep 2; done
mipadi
la source
3
J'aime cette réponse car elle explique quand et pourquoi; (point-virgule) est requis.
M. AndreasGeo
29

Vous pouvez également utiliser la untilcommande:

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

Notez que contrairement à while, untilexécuterait les commandes à l'intérieur de la boucle tant que la condition de test a un état de sortie qui n'est pas nul.


Utiliser une whileboucle:

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

Utiliser une forboucle:

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

Une autre façon d'utiliser until:

until [ ]; do foo; sleep 2; done
devnull
la source
Le until ((0)); do foo; sleep 2; donene semble pas fonctionner. Elle continue infinie.
030
11

Une boucle infinie très simple .. :)

while true ; do continue ; done

Fr votre question ce serait:

while true; do foo ; sleep 2 ; done
Mack
la source
8

J'aime utiliser les points-virgules uniquement pour l'instruction WHILE et l'opérateur && pour que la boucle fasse plus d'une chose ...

Donc je le fais toujours comme ça

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
la source
1
Eh bien, l'utilisation de &&dans la boucle est la même que n'importe quel autre moment n'est-ce pas vraiment. Avez-vous besoin que la deuxième chose se produise uniquement si la première se produit, alors utilisez &&else ;suffit. Vraiment, vous voulez garder le contenu de cette boucle court et simple, idéalement une seule commande, donc une fonction ou un script.
thecoshman
7

Pour un processus simple d'observation, utilisez watchplutôt

Christian Schwarz
la source
6

En utilisant while:

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

Utilisation de la forboucle:

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

Utilisation Recursion, (un peu différent de ce qui précède, l'interruption du clavier ne l'arrêtera pas)

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

Si vous voulez que la boucle while s'arrête après une condition et que votre foocommande retourne non nulle lorsque cette condition est remplie, vous pouvez obtenir la boucle pour se rompre comme ceci:

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

Par exemple, si la foocommande supprime des éléments par lots et renvoie 1 lorsqu'il ne reste plus rien à supprimer.

Cela fonctionne bien si vous disposez d'un script personnalisé qui doit exécuter une commande plusieurs fois jusqu'à une certaine condition. Vous écrivez le script avec 1lequel quitter lorsque la condition est remplie et avec 0quand il doit être exécuté à nouveau.

Par exemple, supposons que vous ayez un script python batch_update.pyqui met à jour 100 lignes dans une base de données et renvoie 0s'il y en a plus à mettre à jour et 1s'il n'y en a plus. La commande suivante vous permettra de mettre à jour les lignes 100 à la fois en dormant pendant 5 secondes entre les mises à jour:

while batch_update.py; do echo 'sleeping...'; sleep 5; done;
Yep_It's_Me
la source
et comment sortiriez-vous?
AK_
Vous effectuez la foocommande exit avec du code 1lorsque vous voulez que la boucle while se casse. J'ai mis à jour ma réponse avec un exemple.
Yep_It's_Me
2

Si je peux donner deux exemples pratiques (avec un peu "d'émotion").

Cela écrit le nom de tous les fichiers terminés par ".jpg" dans le dossier "img":

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

Cela les supprime:

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

J'essaye juste de contribuer.

Roger
la source
1
@JKnight - pour ces exemples, ne le feriez-vous pas ls -1 *.jpgetrm *.jpg
Kevin Fegan
2
Les deux ne sont pas des boucles infinies et pas des boucles while.
Marian
2

Vous pouvez essayer cela aussi AVERTISSEMENT: cela, vous ne devriez pas le faire, mais puisque la question demande une boucle infinie sans fin ... c'est comment vous pouvez le faire.

while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done
grepit
la source
Pourquoi voudriez-vous même faire ça?
gniourf_gniourf
2
parce que Brian Deacon qui a posté la question voulait une boucle infinie. C'est plus d'une façon d'écorcher un chat c'est tout
grepit