Sintaks untuk Bash baris tunggal infinite while

636

Saya mengalami masalah dengan kombinasi titik koma dan / atau kawat gigi yang tepat. Saya ingin melakukan ini, tetapi sebagai one-liner dari baris perintah:

while [ 1 ]
do
    foo
    sleep 2
done
Brian Deacon
sumber
4
ganti baris baru dengan titik koma. Hal yang sama berlaku untuk loop.
Tom
23
@ Tom: itu tidak selalu berhasil. setelah do, Anda harus memiliki perintah pertama, bukan titik koma
Stefano Borini

Jawaban:

1233
while true; do foo; sleep 2; done

Ngomong-ngomong, jika Anda mengetiknya sebagai multiline (seperti yang Anda tunjukkan) di command prompt dan kemudian memanggil histori dengan panah ke atas, Anda akan mendapatkannya di satu baris, diselingi dengan benar.

$ while true
> do
>    echo "hello"
>    sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do    echo "hello";    sleep 2; done
Stefano Borini
sumber
2
"Jika Anda mengetiknya sebagai multiline (seperti yang Anda tunjukkan) pada command prompt dan kemudian memanggil histori dengan panah ke atas, Anda akan mendapatkannya pada satu baris, diselingi dengan benar." itu tidak benar untukku.
Vincent Scheib
@VincentScheib, centang cmdhistopsi jika Anda menggunakan bash?
Alok Singhal
Luar biasa! Bekerja dengan sempurna pada Mavericks (Mac OS-X 10.9) dan memungkinkan saya untuk menjalankan vpn. Openconnect terputus setelah beberapa jam dengan kesalahan cookie yang buruk. Jadi saya meletakkan perintah openconnect dalam skrip shell, sudo su untuk menjadi root, dan gunakan baris cmd ini: while true; do sh /Users/myuser/bin/vpn ; done
Blisterpeanuts
170

Juga dimungkinkan untuk menggunakan perintah tidur dalam kondisi sementara. Membuat one-liner tampak lebih bersih.

while sleep 2; do echo thinking; done
Anssi
sumber
16
Nah ini tidak lebih dari sekedar mengubah sintaks - itu akan menjalankan perintah setelah tidur. Di jawaban sebelumnya, perintah dieksekusi segera. Hanya sesuatu yang perlu diperhatikan.
DanGordon
@DanGordon while echo thinking ; do sleep 2 ; done Tentu saja jika perintah [while] gagal, loop keluar, jadi Anda harus while echo thinking || true ; do sleep 2 ; donetetapi kemudian Anda kembali kewhile true ; ...
Brian Carcich
69

Usus selalu "benar":

while :; do foo; sleep 2; done
ajaaskel
sumber
15
mengapa usus besar selalu benar?
Jürgen Paul
8
@ Pineapple Under the Sea: Dari halaman bash man: (di bagian SHELL BUILTIN PERINTAH) : [arguments] Tidak ada efek; perintah tidak melakukan apa-apa selain memperluas argumen dan melakukan pengalihan tertentu. Kode keluar nol dikembalikan.
Adrian W
2
sintaks ini direkomendasikan sebagai: adalah bagian dari shell itu sendiri yaitu: adalah perintah builtin shell.
avner
@analytik jadi apa maksudmu plus atau minus? ;-)
Brian Carcich
33

Anda dapat menggunakan titik koma untuk memisahkan pernyataan:

$ while [ 1 ]; do foo; sleep 2; done
mipadi
sumber
3
Saya suka jawaban ini karena ini menjelaskan kapan dan mengapa; (titik koma) diperlukan.
Tn. AndreasGeo
29

Anda juga dapat menggunakan untilperintah:

until ((0)); do foo; sleep 2; done

Perhatikan bahwa berbeda dengan while, untilakan menjalankan perintah di dalam loop selama kondisi tes memiliki status keluar yang tidak nol.


Menggunakan whileloop:

while read i; do foo; sleep 2; done < /dev/urandom

Menggunakan forloop:

for ((;;)); do foo; sleep 2; done

Cara lain menggunakan until:

until [ ]; do foo; sleep 2; done
devnull
sumber
The until ((0)); do foo; sleep 2; donetampaknya tidak bekerja. Itu terus menerus tanpa batas.
030
11

Loop tak terbatas yang sangat sederhana .. :)

while true ; do continue ; done

Dari pertanyaan Anda:

while true; do foo ; sleep 2 ; done
Mack
sumber
8

Saya suka menggunakan titik koma hanya untuk pernyataan WHILE, dan operator && untuk membuat loop melakukan lebih dari satu hal ...

Jadi saya selalu melakukannya seperti ini

while true ; do echo Launching Spaceship into orbit && sleep 5s && /usr/bin/launch-mechanism && echo Launching in T-5 && sleep 1s && echo T-4 && sleep 1s && echo T-3 && sleep 1s && echo T-2 && sleep 1s && echo T-1 && sleep 1s && echo liftoff ; done
Thomas
sumber
1
Nah, penggunaan &&dalam loop adalah sama seperti waktu lainnya sebenarnya bukan. Apakah Anda perlu hal kedua terjadi hanya jika yang pertama terjadi, kemudian gunakan yang &&lain ;cukup. Sungguh, Anda ingin menjaga isi loop itu pendek dan sederhana, idealnya hanya satu perintah, jadi fungsi atau skrip.
thecoshman
7

Untuk proses menonton sederhana gunakan watchsaja

Christian Schwarz
sumber
6

Menggunakan while:

while true; do echo 'while'; sleep 2s; done

Menggunakan forLoop:

for ((;;)); do echo 'forloop'; sleep 2; done

Menggunakan Recursion, (sedikit berbeda dari di atas, interupsi keyboard tidak akan menghentikannya)

list(){ echo 'recursion'; sleep 2; list; } && list;
Muhammad Soliman
sumber
5

Jika Anda ingin loop sementara berhenti setelah beberapa kondisi, dan fooperintah Anda mengembalikan non-nol ketika kondisi ini terpenuhi maka Anda bisa mendapatkan loop untuk istirahat seperti ini:

while foo; do echo 'sleeping...'; sleep 5; done;

Misalnya, jika fooperintahnya menghapus hal-hal dalam batch, dan mengembalikan 1 ketika tidak ada yang tersisa untuk dihapus.

Ini berfungsi dengan baik jika Anda memiliki skrip khusus yang perlu menjalankan perintah berkali-kali hingga beberapa syarat. Anda menulis skrip untuk keluar 1saat kondisi terpenuhi dan keluar 0saat harus dijalankan kembali.

Misalnya, Anda memiliki skrip python batch_update.pyyang memperbarui 100 baris dalam database dan mengembalikan 0jika ada lebih banyak untuk memperbarui dan 1jika tidak ada lagi. Perintah berikut akan memungkinkan Anda untuk memperbarui baris 100 sekaligus dengan tidur selama 5 detik antara pembaruan:

while batch_update.py; do echo 'sleeping...'; sleep 5; done;
Yep_It's_Me
sumber
dan bagaimana Anda akan keluar?
AK_
Anda membuat fooperintah keluar dengan kode 1saat Anda ingin loop sementara terputus. Saya telah memperbarui jawaban saya dengan sebuah contoh.
Yep_It's_Me
2

Jika saya bisa memberikan dua contoh praktis (dengan sedikit "emosi").

Ini menulis nama semua file yang diakhiri dengan ".jpg" di folder "img":

for f in *; do if [ "${f#*.}" == 'jpg' ]; then echo $f; fi; done

Ini menghapus mereka:

for f in *; do if [ "${f#*.}" == 'jpg' ]; then rm -r $f; fi; done

Hanya berusaha berkontribusi.

Roger
sumber
1
@JKnight - untuk contoh-contoh ini, tidakkah Anda hanya melakukan ls -1 *.jpgdanrm *.jpg
Kevin Fegan
2
Keduanya bukan loop tak terbatas dan tidak saat loop.
Marian
2

Anda dapat mencoba ini juga PERINGATAN: ini sebaiknya tidak Anda lakukan tetapi karena pertanyaannya adalah meminta infinite loop tanpa akhir ... ini adalah bagaimana Anda dapat melakukannya.

while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done
grepit
sumber
Mengapa Anda melakukan itu?
gniourf_gniourf
2
karena Brian Deacon yang memposting pertanyaan ingin seperti loop infinte. Ini lebih dari satu cara menguliti kucing itu saja
grepit