Bagaimana cara mengulang n kali dalam Bash

9

Saya memiliki skenario di bawah ini seperti:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 
Rocky86
sumber
Ini adalah fitur yang sangat mendasar dalam shell. Apakah Anda bahkan merisetnya?
Peschke
Iya. Tetapi tidak mendapatkan output yang diharapkan dari kode saya. Juga ingin menulis sesingkat mungkin
Rocky86
1
@Peschke, well, mereka membutuhkan setidaknya apa, tiga fitur dasar (loop, kondisional, pengujian file, putus satu lingkaran). Setidaknya pertanyaannya cukup jelas. Meskipun itu bisa berisi sketsa dari apa yang dicoba Rocky, tetapi kemudian seseorang akan menuliskannya kembali dalam jawaban. ;)
ilkkachu

Jawaban:

9

Ada banyak cara untuk melakukan loop ini.

Dengan ksh93sintaks (juga didukung oleh zshdan bash):

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

Untuk setiap shell mirip POSIX:

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

Kedua loop tidur 10 detik di setiap iterasi sebelum menguji keberadaan file lagi.

Setelah loop selesai, Anda harus menguji keberadaan file terakhir kali untuk mengetahui apakah loop keluar karena berjalan 10 kali atau karena file muncul.

Jika Anda mau, dan jika Anda memiliki akses ke alat yang tidak sah, Anda dapat mengganti sleep 10panggilan dengan

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

Ini akan menunggu acara pembuatan file terjadi di direktori saat ini, tetapi akan habis setelah 10 detik. Dengan cara ini loop Anda akan keluar segera setelah nama file yang diberikan muncul (jika muncul).

Kode lengkap, dengan inotifywait(ganti dengan sleep 10jika Anda tidak menginginkannya), mungkin terlihat seperti

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
sumber
Dengan inotify, Anda hampir bisa mengganti seluruh loop. Cukup uji apakah file ada di sana, dan jika tidak, tunggu hingga 100 detik. Hampir, karena file dapat dibuat hanya antara tes dan inotify, dan Anda akan tidur selama 100 detik penuh sebelum waktu habis ...
ilkkachu
1
@ilkkachu Ya, itu ide yang bagus, tapi di sini saya hanya menggunakan inotifywaitsebagai pengganti drop-in sleep.
Kusalananda
8

Jika jumlah bukan variabel, Anda dapat menggunakan ekspansi brace:

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

Jika jumlah adalah variabel, Anda dapat menggunakan seqperintah:

count=10
for i in $(seq $count)
do
  whatever
done
xenoid
sumber
Saya ingin mengulang hanya jika file tidak ditemukan (maks. 10 kali). Jika ditemukan katakanlah ketiga kalinya lalu keluar dengan sukses
Rocky86
@ Rocky86: Ini tidak bertentangan dengan solusi yang diusulkan oleh xenoid. Tidak ada yang memaksa Anda untuk menghitung sampai akhir ....
user1934428
Saya suka yang ini$(seq $count)
Pekerja
0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

meskipun test -e file && exitlebih fleksibel

mikeserv
sumber
Mengapa tanda tanya? Perhatikan bahwa perilaku untuk glob di target pengalihan bervariasi antara shell.
Stéphane Chazelas
2
Perhatikan bahwa ia memiliki efek samping membuka file, yang untuk fifos misalnya bisa sangat buruk (lebih buruk dengan symlink ke / dev / watchdog di Linux misalnya)
Stéphane Chazelas
Bahkan di Bash, di mana ini akan mencari file seperti exists1atau seperti itu, masih mencetak banyak kesalahan jika / ketika file yang cocok tidak ditemukan. (Juga kesalahan jika ada beberapa pertandingan.) Setiap shell lain yang saya uji tampaknya memberikan kesalahan dalam hal apapun ...
ilkkachu
@ikkachu - yeah. itu intinya. jika kesalahan terjadi, skrip melaporkan. jika stderr harus ditekan, tekan saja done 2<>/dev/null. apakah bashitu dituliskan? Saya pikir itu hanya berhasil dalam -ikonteks nteraktif. masih, exists?sebanyak nama pengisi sebagai file. tapi ya, saya benci mengutip pengalihan - jika sekrup begitu banyak.
mikeserv
@ Stéphane - tanpa alasan, sungguh. tapi ya, fifos, tidak dapat dibaca ... itu sebabnya saya perhatikan test -e.
mikeserv