Bash'de bir dosya olup olmadığını test etmek için while döngüsü


98

Bir txt dosyasında yalnızca varsa belirli değişiklikleri yapan bir kabuk komut dosyası üzerinde çalışıyorum, ancak bu test döngüsü çalışmıyor, nedenini merak ediyorum? Teşekkür ederim!

while [ ! -f /tmp/list.txt ] ;
do
      sleep 2
done

3
Şaşırdığımı söyleyemem; bu döngü hiçbir şeyi değiştirmeye çalışmaz.
Ignacio Vazquez-Abrams

Noktalı virgül gereksizdir. Bu test döngüsü ne şekilde çalışmıyor? /Tmp/list.txt dosyası var olana kadar yinelemeli olarak 2 saniye uyuyacaktır.
Jonathan Leffler

5
Benim için çalışıyor - dosya komut dosyasının dışında oluşturulduğunda döngü sona erer.

1
aslında, bu döngü sadece dosya orada olana kadar beklemeye hizmet ediyor, betiğimin geri kalanı değişiklikleri yapıyor ...: p
Zenet

1
Sonra while döngüsü çalışır, sadece ben ... üzgünüm.
Zenet 04

Yanıtlar:


150

"Çalışmıyor" dediğinizde, işe yaramadığını nasıl anlarsınız?

Ekleyerek dosyanın gerçekten var olup olmadığını anlamaya çalışabilirsiniz:

while [ ! -f /tmp/list.txt ]
do
  sleep 2 # or less like 0.2
done
ls -l /tmp/list.txt

Ayrıca, 'echo $ SHELL' yazarak bir Bash (veya ilgili) kabuğu kullandığınızdan emin olabilirsiniz. CSH ve TCSH'nin bu döngü için biraz farklı bir anlambilim kullandığını düşünüyorum.


Neden ters dosya denetimi kullanıyorsunuz? Bunun yerine [-f /tmp/list.txt] kullanılmamalı mı?
valentt

2
@valentt Hiçbir döngü, kelimenin tam anlamıyla "DEĞİL dosya mevcutken uyu" demez .. Eğer 'DEĞİL' seçeneğini kaldırırsanız, döngü anında kırılır
Kenyakorn Ketsombut

2
1 satırda:while [ ! -f /tmp/list.txt ]; do sleep 2; done; ls -l /tmp/list.txt
DrumM

55

Linux'taysanız ve inotify-tools yüklediyseniz, bunu yapabilirsiniz:

file=/tmp/list.txt
while [ ! -f "$file" ]
do
    inotifywait -qqt 2 -e create -e moved_to "$(dirname $file)"
done

Bu, hala her "x" saniyede bir yoklama yaparken uykunun getirdiği gecikmeyi azaltır. Gerekli olduklarını tahmin ediyorsanız daha fazla etkinlik ekleyebilirsiniz.


4
Verimlilik için +1. Uyku ile havuz yapmak çirkin. İnotifywait'i bilmeyen insanlar için - inotify-tools paketinde.
Michał Šrajer

7
Bu son derece kullanışlı bir araçtır. Döngünün neden olduğunu merak eden herkes için, yaratma ve bekleme arasındaki olası yarış koşullarıyla uğraşmak ve inotifywait'in --excludedosya adlarını filtrelemesi gerektiği, ancak dosya adı dışındaki--include her şeyi göz ardı etmemesi gerektiğinden . Yukarıdaki komut bunun yerine argümanı kullanmalıdır . -qq>&/dev/null
Craig Ringer

1
t --timeoutkontrol sıklığı değil, değil mi? İnotifywait'in amacı, anket olmaması
Alex Dean

1
@AlexDean Zaman aşımı bir yarış durumunu önlemek içindir. Uyku ile yoklama yavaştır çünkü döngü uyku sırasında çıkmaz, ancak inotifywait bir olay görürse zaman aşımından önce çıkacaktır.
yingted

1
@AlexDean Evet, ancak bir TOCTTOU yarış durumunu önlemek için gereklidir. Aksi takdirde, inotifywaitbir dosya olayları dinlemeye başlamadan hemen önce oluşturulursa süresiz olarak askıda kalabilir.
05

4

Ben de aynı sorunu yaşadım, koy! parantezlerin dışında;

while ! [ -f /tmp/list.txt ];
do
    echo "#"
    sleep 1
done

Ayrıca, döngünün içine bir yankı eklerseniz, döngünün içine girip girmediğinizi size söyleyecektir.


2

Benzer bir sorunla karşılaştım ve beni buraya yönlendirdi, bu yüzden çözümümü aynı deneyimi yaşayan herkes için bırakmak istedim.

cat /tmp/list.txtİçeriğin hemen dosyaya yerleştirildiğinden emin olmama rağmen, çalıştırırsam dosyanın boş olacağını fark ettim. sleep 1;Hemen önüne bir koyarsam ortaya çıkıyorcat /tmp/list.txtBeklendiği gibi çalışmadan . Dosyanın oluşturulduğu zaman ile yazıldığı zaman arasında veya bu satırlarda bir gecikme olmuş olmalı.

Son kodum:

while [ ! -f /tmp/list.txt ];
do
    sleep 1;
done;
sleep 1;
cat /tmp/list.txt;

Umarım bu, birisine sinir bozucu bir yarım saat kazandırır!


1

@ Zane-hooper gibi, NFS'de de benzer bir sorun yaşadım. Paralel / dağıtılmış dosya sistemlerinde, bir makinede bir dosya yaratmanız ile diğer makinenin onu "görmesi" arasındaki gecikme çok büyük olabilir, bu nedenle, while döngüsü çıkmadan önce dosyanın oluşturulmasının ardından tam bir dakika bekleyebilirim (ve zaten silinmiş bir dosyayı "görmenin" bir sonucu da vardır).

Bu , komut dosyasının "çalışmadığı" yanılsamasını yaratır , oysa aslında topu düşüren dosya sistemidir.

Bunu anlamam biraz zaman aldı, umarım birine biraz zaman kazandırır.

PS Bu ayrıca can sıkıcı sayıda "Eski dosya işleyici" hatalarına neden olur.


0

bash ve sh ile çalışır:

touch /tmp/testfile
sleep 10 && rm /tmp/testfile &
until ! [ -f /tmp/testfile ]
do
   echo "testfile still exist..."
   sleep 1
done
echo "now testfile is deleted.."

0

İşte zaman aşımına sahip bir sürüm, böylece belirli bir süre sonra döngü bir hatayla biter:

# After 60 seconds the loop will exit
timeout=60

while [ ! -f /tmp/list.txt ];
do
  # When the timeout is equal to zero, show an error and leave the loop.
  if [ "$timeout" == 0 ]; then
    echo "ERROR: Timeout while waiting for the file /tmp/list.txt."
    exit 1
  fi

  sleep 1

  # Decrease the timeout of one
  ((timeout--))
done

-3

böyle yap

while true
do
  [ -f /tmp/list.txt ] && break
  sleep 2
done
ls -l /tmp/list.txt
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.