So wiederholen Sie die Schleife n-mal in Bash

9

Ich habe unten Szenario wie:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 
Rocky86
quelle
Dies ist eine sehr grundlegende Funktion in Muscheln. Hast du es überhaupt recherchiert?
Peschke
Ja. Aber ich bekomme keine erwartete Ausgabe von meinem Code.
Ich
1
@Peschke, nun, sie würden mindestens drei grundlegende Funktionen benötigen (Schleifen, Bedingungen, Testen der Datei, Ausbrechen einer Schleife). Zumindest ist die Frage so wie sie ist ganz klar. Es könnte zwar eine Skizze dessen enthalten, was Rocky versucht hat, aber dann würde jemand es trotzdem vollständig in die Antworten umschreiben. ;)
ilkkachu

Antworten:

9

Es gibt viele Möglichkeiten, diese Schleife durchzuführen.

Mit ksh93Syntax (auch unterstützt von zshund bash):

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

Für jede POSIX-ähnliche Shell:

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

Beide Schleifen schlafen in jeder Iteration 10 Sekunden, bevor die Existenz der Datei erneut getestet wird.

Nachdem die Schleife beendet wurde, müssen Sie ein letztes Mal prüfen, ob die Datei vorhanden ist, um herauszufinden, ob die Schleife aufgrund einer zehnmaligen Ausführung oder aufgrund der angezeigten Datei beendet wurde.

Wenn Sie möchten und Zugriff auf inotify-tools haben, können Sie den sleep 10Anruf durch ersetzen

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

Dies würde warten, bis ein Dateierstellungsereignis im aktuellen Verzeichnis auftritt, würde jedoch nach 10 Sekunden eine Zeitüberschreitung aufweisen. Auf diese Weise wird Ihre Schleife beendet, sobald der angegebene Dateiname angezeigt wird (falls er angezeigt wird).

Der vollständige Code mit inotifywait(ersetzen durch, sleep 10wenn Sie das nicht möchten) sieht möglicherweise so aus

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
quelle
Mit inotify können Sie fast die gesamte Schleife ersetzen. Testen Sie einfach, ob die Datei vorhanden ist, und warten Sie 100 Sekunden, bis sie nicht angezeigt wird. Fast, da die Datei nur zwischen dem Test und dem Inotify erstellt werden konnte und Sie die vollen 100 Sekunden schlafen würden, bevor Sie das
Zeitlimit überschreiten
1
@ilkkachu Ja, das ist eine gute Idee, aber hier verwende ich sie nur inotifywaitals Ersatz für sleep.
Kusalananda
8

Wenn die Anzahl keine Variable ist, können Sie die Klammererweiterung verwenden:

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

Wenn die Anzahl eine Variable ist, können Sie den folgenden seqBefehl verwenden:

count=10
for i in $(seq $count)
do
  whatever
done
Xenoid
quelle
Ich möchte nur eine Schleife durchführen, wenn die Datei nicht gefunden wird (max. 10 Mal). Wenn gefunden, sagen wir zum dritten Mal, dann
beenden Sie
@ Rocky86: Dies widerspricht nicht der von Xenoid vorgeschlagenen Lösung. Niemand zwingt Sie, bis zum Ende zu zählen ....
user1934428
Ich mag dieses$(seq $count)
Arbeiter
0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

obwohl test -e file && exitist flexibler

mikeserv
quelle
Warum das Fragezeichen? Beachten Sie, dass das Verhalten für Globs im Ziel von Umleitungen zwischen den Shells variiert.
Stéphane Chazelas
2
Beachten Sie, dass es den Nebeneffekt hat, die Datei zu öffnen, was zum Beispiel für fifos ziemlich schlecht sein kann (schlimmer mit einem Symlink zu / dev / watchdog unter Linux zum Beispiel)
Stéphane Chazelas
Selbst in Bash, wo dies nach einer ähnlichen Datei suchen würde exists1, werden immer noch eine Reihe von Fehlern ausgegeben, wenn keine passende Datei gefunden wird. (Auch es gibt Fehler, wenn es mehrere Übereinstimmungen gibt.) Jede andere Shell, die ich getestet habe, scheint auf jeden Fall Fehler zu geben ...
ilkkachu
@ikkachu - ja. das war irgendwie der Punkt. Wenn der Fehler auftritt, meldet das Skript. Wenn stderr unterdrückt werden soll, unterdrücken Sie es done 2<>/dev/null. Ist bashdas ein Skript? Ich dachte, dass es das nur in einem -interaktiven Kontext bewirkt. Trotzdem exists?ist es so viel wie ein Füllername wie file. aber ja, ich hasse es, in Weiterleitungen zu zitieren - wenn es so viel vermasselt.
Mikeserv
@ Stéphane - eigentlich kein Grund. aber ja, fifos, unlesbar ... deshalb habe ich es bemerkt test -e.
Mikeserv