Come ripetere loop n volte in Bash


9

Ho uno scenario di seguito come:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 

Questa è una funzionalità di base nelle shell. L'hai mai fatto ricerche?
Peschke,

Sì. Ma non ottenere l'output previsto dal mio codice. Voglio anche scrivere il più abbreviato possibile
Rocky86,

1
@Peschke, beh, avrebbero bisogno almeno di cosa, tre funzionalità di base (loop, condizionali, test del file, interruzione di un ciclo). Almeno la domanda è abbastanza chiara com'è. Anche se potrebbe contenere uno schizzo di ciò che Rocky ha provato, ma poi qualcuno lo riscriverebbe comunque pieno nelle risposte. ;)
ilkkachu il

Risposte:


9

Esistono molti modi per eseguire questo ciclo.

Con ksh93sintassi (supportato anche da zshe bash):

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

Per qualsiasi shell simile a POSIX:

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

Entrambi i loop dormono 10 secondi in ogni iterazione prima di testare nuovamente l'esistenza del file.

Dopo che il ciclo è terminato, dovrai verificare l'esistenza del file un'ultima volta per capire se il ciclo è uscito a causa dell'esecuzione di 10 volte o della comparsa del file.

Se lo desideri e se hai accesso a inotify-tools, puoi sostituire la sleep 10chiamata con

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

Ciò aspetterebbe che si verifichi un evento di creazione del file nella directory corrente, ma sarebbe scaduto dopo 10 secondi. In questo modo il tuo loop verrebbe chiuso non appena appariva il nome file dato (se appariva).

Il codice completo, con inotifywait(sostituisci con sleep 10se non lo desideri), potrebbe apparire come

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

Con inotify, potresti quasi sostituire l'intero loop. Basta verificare se il file è presente e, in caso contrario, inotify attendere per 100 secondi. Quasi, poiché il file potrebbe essere creato proprio tra il test e l'inotify e dormiresti per tutti i 100 secondi prima del timeout ...
ilkkachu

1
@ilkkachu Sì, è una buona idea, ma qui sto solo usando inotifywaitcome sostituto drop-in sleep.
Kusalananda

8

Se il conteggio non è una variabile è possibile utilizzare l'espansione del controvento:

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

Se il conteggio è una variabile è possibile utilizzare il seqcomando:

count=10
for i in $(seq $count)
do
  whatever
done

Voglio eseguire il ciclo solo se il file non viene trovato (massimo 10 volte). Se trovato, diciamo la terza volta, quindi esci con successo
Rocky86,

@ Rocky86: questo non contraddice la soluzione proposta da xenoid. Nessuno ti obbliga a contare fino alla fine ....
user1934428

Mi piace questo$(seq $count)
Worker

0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

sebbene test -e file && exitsia più flessibile


Perché il punto interrogativo? Si noti che il comportamento dei globs nel target dei reindirizzamenti varia tra le shell.
Stéphane Chazelas il

2
Si noti che ha l'effetto collaterale di aprire il file, che per esempio per i cinquos può essere piuttosto male (peggio con un link simbolico a / dev / watchdog su Linux per esempio)
Stéphane Chazelas,

Anche in Bash, dove questo cercherebbe un file simile exists1o simile, stampa comunque una serie di errori se / quando non viene trovato un file corrispondente. (Inoltre si verificano errori in caso di più corrispondenze.) Qualsiasi altra shell che ho testato sembra dare errori in ogni caso ...
ilkkachu

@ikkachu - sì. quello era un po 'il punto. se si verifica l'errore, lo script riporta. se lo stderr deve essere soppresso, sopprimilo done 2<>/dev/null. fa bashquello scritto? ho pensato che fosse solo in un -icontesto nterattivo. tuttavia, exists?è un nome di riempimento quanto file. ma sì, odio citare i reindirizzamenti - se le viti aumentano così tanto.
Mikeserv,

@ Stéphane - nessuna ragione, davvero. ma sì, quindici, illeggibili ... ecco perché l'ho notato test -e.
mikeserv,
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.