While loop untuk menguji apakah file ada di bash

97

Saya sedang mengerjakan skrip shell yang melakukan perubahan tertentu pada file txt hanya jika memang ada, namun loop pengujian ini tidak berfungsi, saya bertanya-tanya mengapa? Terima kasih!

while [ ! -f /tmp/list.txt ] ;
do
      sleep 2
done
Zenet
sumber
3
Saya tidak bisa mengatakan bahwa saya terkejut; loop itu tidak mencoba mengubah apa pun.
Ignacio Vazquez-Abrams
Titik koma berlebihan. Dengan cara apa loop tes itu tidak berfungsi? Ini akan tidur berulang selama 2 detik sampai file /tmp/list.txt ada.
Jonathan Leffler
5
Bekerja untuk saya - loop berakhir ketika file dibuat di luar skrip.
1
Faktanya, loop ini hanya berfungsi untuk menunggu sampai file ada di sana, sisa skrip saya melakukan perubahan ...: p
Zenet
1
Kemudian loop sementara bekerja, hanya saya ... maaf.
Zenet

Jawaban:

149

Ketika Anda mengatakan "tidak berhasil", bagaimana Anda tahu itu tidak berhasil?

Anda dapat mencoba mencari tahu apakah file tersebut benar-benar ada dengan menambahkan:

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

Anda juga dapat memastikan bahwa Anda menggunakan shell Bash (atau terkait) dengan mengetik 'echo $ SHELL'. Saya pikir CSH dan TCSH menggunakan semantik yang sedikit berbeda untuk loop ini.

CWF
sumber
Mengapa Anda menggunakan pemeriksaan file terbalik? Bukankah seharusnya sementara [-f /tmp/list.txt] digunakan?
valentt
2
@valentt Tidak ada loop hew yang mengatakan secara harfiah "sementara file NOT ada, lakukan tidur" .. jika Anda menghapus 'NOT' loop akan langsung putus
Kenyakorn Ketsombut
2
dalam 1 baris:while [ ! -f /tmp/list.txt ]; do sleep 2; done; ls -l /tmp/list.txt
DrumM
55

Jika Anda menggunakan linux dan telah menginstal alat inotify, Anda dapat melakukan ini:

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

Ini mengurangi penundaan yang disebabkan oleh tidur sambil tetap mengumpulkan setiap "x" detik. Anda dapat menambahkan lebih banyak acara jika Anda mengantisipasinya diperlukan.

yingted
sumber
4
1 untuk efisiensi. Menyatukan dengan tidur itu jelek. Untuk orang-orang yang tidak mengetahui inotifywait - ada dalam paket inotify-tools.
Michał Šrajer
7
Itu alat yang sangat berguna. Bagi siapa pun yang bertanya-tanya mengapa loop, ini untuk menangani kemungkinan kondisi balapan antara pembuatan dan menunggu dan karena inotifywait harus --excludememfilter nama file, tetapi tidak --includemengabaikan semuanya kecuali nama file. Perintah di atas harus menggunakan -qqargumen daripada >&/dev/nullmeskipun.
Craig Ringer
t adalah --timeout, bukan frekuensi pemeriksaan, bukan? Inti dari inotifywait adalah bahwa tidak ada pemungutan suara
Alex Dean
1
@AlexDean Batas waktu adalah untuk mencegah kondisi balapan. Polling dengan tidur lambat karena loop tidak akan keluar selama tidur, tetapi inotifywait akan keluar sebelum batas waktu jika melihat suatu peristiwa.
yingted
1
@AlexDean Ya, tapi itu perlu untuk mencegah kondisi balapan TOCTTOU. Jika tidak, inotifywaitbisa hang tanpa batas jika file dibuat tepat sebelum mulai mendengarkan acara.
yingted
4

Saya memiliki masalah yang sama, letakkan! di luar tanda kurung;

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

Juga, jika Anda menambahkan gema di dalam loop, itu akan memberi tahu Anda apakah Anda masuk ke dalam loop atau tidak.

David Cox
sumber
2

Saya mengalami masalah serupa dan itu membawa saya ke sini jadi saya hanya ingin meninggalkan solusi saya untuk siapa saja yang mengalami hal yang sama.

Saya menemukan bahwa jika saya menjalankan cat /tmp/list.txtfile tersebut akan kosong, meskipun saya yakin ada konten yang langsung ditempatkan di file. Ternyata jika saya meletakkan sleep 1;sebelum cat /tmp/list.txtitu bekerja seperti yang diharapkan. Pasti ada penundaan antara waktu file dibuat dan waktu itu ditulis, atau sesuatu seperti itu.

Kode terakhir saya:

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

Semoga ini membantu menyelamatkan seseorang dari setengah jam yang membuat frustrasi!

Zane
sumber
1

Seperti @zane-hooper, saya mengalami masalah serupa di NFS. Pada filesystem paralel / terdistribusi, jeda antara Anda membuat file di satu mesin dan mesin lain "melihat" itu bisa sangat besar, jadi saya bisa menunggu hingga satu menit penuh setelah pembuatan file sebelum while loop keluar (dan ada juga efek sampingnya "melihat" file yang sudah dihapus).

Ini menciptakan ilusi bahwa skrip "tidak berfungsi" , padahal sebenarnya itu adalah sistem file yang menjatuhkan bola.

Ini membutuhkan waktu beberapa saat bagi saya untuk memikirkannya, semoga dapat menghemat waktu seseorang.

PS Ini juga menyebabkan sejumlah kesalahan "Stale file handler" yang mengganggu.

Ruslan Shaydulin
sumber
0

bekerja dengan bash dan sh keduanya:

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.."
neerajmalve.dll
sumber
0

Berikut adalah versi dengan batas waktu sehingga setelah beberapa waktu pengulangan berakhir dengan kesalahan:

# 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
ZedTuX
sumber
-3

lakukan seperti ini

while true
do
  [ -f /tmp/list.txt ] && break
  sleep 2
done
ls -l /tmp/list.txt
anjing hantu74
sumber