Comment répéter la boucle n fois dans Bash

9

J'ai ci-dessous un scénario comme:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 
Rocky86
la source
Il s'agit d'une fonctionnalité très basique dans les coquilles. L'avez-vous même recherché?
Peschke
Oui. Mais ne pas obtenir la sortie attendue de mon code.
Je
1
@Peschke, eh bien, ils auraient besoin d'au moins quoi, trois fonctionnalités de base (boucles, conditions, tester le fichier, sortir d'une boucle). Au moins, la question est assez claire telle qu'elle est. Bien qu'il puisse contenir un croquis de ce que Rocky a essayé, mais quelqu'un le réécrirait de toute façon dans les réponses. ;)
ilkkachu

Réponses:

9

Il existe plusieurs façons de faire cette boucle.

Avec la ksh93syntaxe (également prise en charge par zshet bash):

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    sleep 10
done

Pour tout shell de type POSIX:

n=0
while [ "$n" -lt 10 ] && [ ! -e filename ]; do
    n=$(( n + 1 ))
    sleep 10
done

Les deux boucles dorment 10 secondes à chaque itération avant de tester à nouveau l'existence du fichier.

Une fois la boucle terminée, vous devrez tester l'existence du fichier une dernière fois pour déterminer si la boucle s'est terminée en raison d'une exécution 10 fois ou en raison de l'apparition du fichier.

Si vous le souhaitez, et si vous avez accès aux outils inotify, vous pouvez remplacer l' sleep 10appel par

inotifywait -q -t 10 -e create ./ >/dev/null

Cela attendrait qu'un événement de création de fichier se produise dans le répertoire en cours, mais expirerait après 10 secondes. De cette façon, votre boucle se fermerait dès que le nom de fichier donné apparaît (s'il apparaît).

Le code complet, avec inotifywait(remplacer par sleep 10si vous ne le souhaitez pas), peut ressembler à

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    inotifywait -q -t 10 -e create ./ >/dev/null
done

if [ -e filename ]; then
    echo 'file appeared!'
else
    echo 'file did not turn up in time'
fi
Kusalananda
la source
Avec inotify, vous pourriez presque remplacer la boucle entière. Testez simplement si le fichier est là, et sinon, inotifywait pendant 100 secondes. Presque, car le fichier pourrait être créé juste entre le test et l'inotify, et vous dormeriez pendant 100 secondes avant de vous
expirer
1
@ilkkachu Oui, c'est une bonne idée, mais ici, je ne fais que l'utiliser inotifywaitcomme un remplacement pour sleep.
Kusalananda
8

Si le nombre n'est pas une variable, vous pouvez utiliser l'expansion d'accolade:

for i in {1..10}   # you can also use {0..9}
do
  whatever
done

Si le nombre est une variable, vous pouvez utiliser la seqcommande:

count=10
for i in $(seq $count)
do
  whatever
done
xénoïde
la source
Je veux faire une boucle uniquement si le fichier n'est pas trouvé (max. 10 fois). S'il est trouvé, disons la 3e fois, puis quittez avec succès
Rocky86
@ Rocky86: Cela ne contredit pas la solution proposée par xenoid. Personne ne vous oblige à compter jusqu'à la fin ....
user1934428
J'aime celui-ci$(seq $count)
Travailleur
0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

mais test -e file && exitest plus souple

mikeserv
la source
Pourquoi le point d'interrogation? Notez que le comportement des globes dans la cible des redirections varie selon les shells.
Stéphane Chazelas
2
Notez qu'il a pour effet secondaire d'ouvrir le fichier, ce qui par exemple pour fifos peut être assez mauvais (pire avec un lien symbolique vers / dev / watchdog sur Linux par exemple)
Stéphane Chazelas
Même dans Bash, où cela chercherait un fichier tel exists1ou tel, il affiche toujours un tas d'erreurs si / quand un fichier correspondant n'est pas trouvé. (Il y a aussi des erreurs s'il y a plusieurs correspondances.) Tout autre shell que j'ai testé semble donner des erreurs dans tous les cas ...
ilkkachu
@ikkachu - ouais. c'était un peu le point. si l'erreur se produit, le script signale. si stderr doit être supprimé, supprimez-le done 2<>/dev/null. est- bashce que c'est scripté? je pensais que cela n'effectuait cela que dans un -icontexte interactif. encore, exists?est autant un nom de remplissage que file. mais oui, je déteste citer les redirections - si les vis sont tellement en place.
mikeserv
@ Stéphane - vraiment aucune raison. mais oui, fifos, illisibles ... c'est pourquoi je l'ai noté test -e.
mikeserv