Bash'te döngü n kez nasıl tekrarlanır


9

Aşağıdaki gibi senaryo var:

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

Bu kabuklarda çok temel bir özelliktir. Hatta araştırdın mı?
Peschke

Evet. Ancak kodumdan beklenen çıktıyı alamıyorum. Ayrıca olabildiğince kısaltılmış olarak yazmak istiyorum
Rocky86

1
@Peschke, en azından üç temel özelliğe ihtiyaç duyuyorlardı (döngüler, koşullu, dosyayı test etme, bir döngüden kopma). En azından soru olduğu gibi oldukça açık. Rocky'nin denediklerinin bir taslağını içerebilmesine rağmen, birileri yine de cevaplarda tam olarak yeniden yazacaktı. ;)
ilkkachu

Yanıtlar:


9

Bu döngüyü yapmanın birçok yolu vardır.

İle ksh93sözdizimi (ayrıca desteklediği zshve bash):

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

POSIX benzeri herhangi bir kabuk için:

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

Her iki döngü de dosyanın varlığını test etmeden önce her yinelemede 10 saniye uyur.

Döngü bittikten sonra, döngünün 10 kez çalıştırılmasından veya dosyanın görünmesinden dolayı çıkıp çıkmadığını anlamak için dosyanın son varlığını test etmeniz gerekecektir.

İsterseniz ve inotify araçlarına erişiminiz varsa, sleep 10çağrıyı

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

Bu, geçerli dizinde bir dosya oluşturma olayının gerçekleşmesini bekler, ancak 10 saniye sonra zaman aşımına uğrar. Bu yolla, verilen dosya adı görünür görünmez (görünürse) döngünüz çıkacaktır.

İle tam kod inotifywait( sleep 10bunu istemiyorsanız değiştirin ),

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

İnotify ile neredeyse tüm döngüyü değiştirebilirsiniz. Dosyanın orada olup olmadığını test edin ve eğer değilse, 100 saniye beklemeyin. Neredeyse, dosya sadece test ile
inotify

1
@ilkkachu Evet, bu iyi bir fikir, ama burada sadece inotifywaityerine bir yedek olarak kullanıyorum sleep.
Kusalananda

9

Sayı bir değişken değilse küme ayracı genişletmeyi kullanabilirsiniz:

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

Sayı bir değişkense şu seqkomutu kullanabilirsiniz :

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

Yalnızca dosya bulunamazsa (en fazla 10 kez) döngü yapmak istiyorum. Eğer bulunursa, 3. kez diyelim, sonra başarıyla çıkın
Rocky86

@ Rocky86: Bu, ksenoid tarafından önerilen çözümle çelişmez. Kimse sonuna kadar saymaya zorlar ....
user1934428

Bunu beğendim$(seq $count)
İşçi

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

test -e file && exitdaha esnek olsa da


Neden soru işareti? Yönlendirme hedefindeki globların davranışının kabuklar arasında değiştiğini unutmayın.
Stéphane Chazelas

2
Dosyayı açmanın yan etkisi olduğunu unutmayın; örneğin, beşli için oldukça kötü olabilir (örneğin Linux'ta / dev / watchdog için bir symlink ile daha da kötüsü)
Stéphane Chazelas

Bunun gibi bir dosyayı arayacağı Bash'de bile, exists1eşleşen bir dosya bulunamazsa / bulunsa bile bir sürü hata yazdırır. (Ayrıca birden fazla eşleşme varsa hatalar.) Test ettiğim herhangi bir kabuk her durumda hata veriyor gibi görünüyor ...
ilkkachu

@ikkachu - evet. mesele buydu. hata oluşursa, komut dosyası raporlanır. stderr bastırılmalıysa, bastırın done 2<>/dev/null. mu basho metne geliyor? bunu sadece etkili -iolmayan bir bağlamda etkilediğini düşündüm . Yine de, exists?dolgu adı kadar file. ama evet, yönlendirmelerden alıntı yapmaktan nefret ediyorum - eğer çok fazla vidalanırsa.
mikeserv

@ Stéphane - sebep yok, gerçekten. ama evet, fifos, okunamaz ... bu yüzden not aldım test -e.
mikeserv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.