Como repetir loop n vezes no Bash

9

Eu tenho abaixo cenário como:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 
Rocky86
fonte
Esta é uma característica muito básica nas conchas. Você pesquisou mesmo?
Peschke
Sim. Mas não obtendo a saída esperada do meu código. Também quero escrever como abreviado como possível
Rocky86
1
@Peschke, bem, eles precisariam de pelo menos três características básicas (loops, condicionais, teste do arquivo, quebra de loop). Pelo menos a questão é bastante clara. Embora pudesse conter um esboço do que Rocky tentou, mas alguém o reescreveria nas respostas de qualquer maneira. ;)
ilkkachu

Respostas:

9

Existem muitas maneiras de fazer esse loop.

Com ksh93sintaxe (também suportada por zshe bash):

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

Para qualquer shell semelhante ao POSIX:

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

Ambos os loops dormem 10 segundos em cada iteração antes de testar a existência do arquivo novamente.

Após a conclusão do loop, você terá que testar a existência do arquivo pela última vez para descobrir se o loop saiu devido à execução 10 vezes ou devido à exibição do arquivo.

Se desejar, e se você tiver acesso às ferramentas inotify, poderá substituir a sleep 10chamada por

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

Isso aguardaria a ocorrência de um evento de criação de arquivo no diretório atual, mas atingia o tempo limite após 10 segundos. Dessa forma, seu loop sairá assim que o nome do arquivo especificado aparecer (se ele aparecer).

O código completo, com inotifywait(substitua por, sleep 10se você não quiser isso), pode parecer

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
fonte
Com o inotify, você quase poderia substituir o loop inteiro. Apenas teste se o arquivo está lá e, se não estiver, aguarde 100 segundos. Quase, uma vez que o arquivo pode ser criada apenas entre o teste ea inotify, e você dormiria para o total de 100 segundos antes do tempo limite ...
ilkkachu
1
@ilkkachu Sim, isso é uma boa idéia, mas aqui eu estou usando apenas inotifywaitcomo um substituto para sleep.
Kusalananda
8

Se a contagem não for uma variável, você poderá usar a expansão entre chaves:

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

Se a contagem for uma variável, você pode usar o seqcomando:

count=10
for i in $(seq $count)
do
  whatever
done
xenoid
fonte
Eu quero fazer um loop apenas se o arquivo não for encontrado (no máximo 10 vezes). Se for encontrado Vamos dizer que o tempo 3ª e sai
Rocky86
@ Rocky86: Isso não contradiz a solução proposta pela xenoid. Ninguém o obriga a contar até o fim ....
user1934428
Eu gosto deste$(seq $count)
Trabalhador
0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

embora test -e file && exitseja mais flexível

mikeserv
fonte
Por que o ponto de interrogação? Observe que o comportamento dos globs no destino dos redirecionamentos varia entre os shells.
Stéphane Chazelas
2
Note que tem o efeito colateral de abrir o arquivo, o que para fifos por exemplo pode ser muito ruim (pior com um link simbólico para / dev / watchdog no Linux, por exemplo)
Stéphane Chazelas
Mesmo no Bash, onde isso procuraria um arquivo como exists1esse, ele ainda imprime vários erros se / quando um arquivo correspondente não for encontrado. (Também erros se houver várias correspondências.) Qualquer outra shell Testei parece dar erros em qualquer caso ...
ilkkachu
@ikkachu - sim. esse era o ponto. se o erro ocorrer, o script será reportado. se stderr deve ser suprimido, suprima-o done 2<>/dev/null. faz bashisso com script? eu pensei que isso só acontecia em um -icontexto não-ativo . ainda, exists?é tanto quanto um nome de preenchimento como file. Mas sim, eu odeio citar em redirecionamentos - se parafusos de modo muito para cima.
mikeserv
@ Stéphane - sem motivo, realmente. mas sim, fifos, ilegíveis ... é por isso que eu notei test -e.
mikeserv