Cách lặp lại vòng lặp n lần trong Bash


9

Tôi có kịch bản dưới đây như:

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

Đây là một tính năng rất cơ bản trong vỏ. Bạn thậm chí đã nghiên cứu nó?
Peschke

Đúng. Nhưng không nhận được đầu ra mong đợi từ mã của tôi. Cũng muốn viết càng viết tắt càng tốt
Rocky86

1
@Peschke, tốt, họ sẽ cần ít nhất ba tính năng cơ bản (vòng lặp, điều kiện, kiểm tra tệp, thoát ra khỏi vòng lặp). Ít nhất là câu hỏi khá rõ ràng. Mặc dù nó có thể chứa một bản phác thảo về những gì Rocky đã cố gắng, nhưng sau đó ai đó sẽ viết lại nó đầy đủ trong các câu trả lời. ;)
ilkkachu

Câu trả lời:


9

Có nhiều cách để thực hiện vòng lặp này.

Với ksh93cú pháp (cũng được hỗ trợ bởi zshbash):

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

Đối với mọi vỏ giống như POSIX:

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

Cả hai vòng lặp ngủ 10 giây trong mỗi lần lặp trước khi kiểm tra lại sự tồn tại của tệp.

Sau khi vòng lặp kết thúc, bạn sẽ phải kiểm tra sự tồn tại của tệp lần cuối để tìm hiểu xem vòng lặp đã thoát do chạy 10 lần hay do tệp xuất hiện.

Nếu bạn muốn và nếu bạn có quyền truy cập vào các công cụ inotify, bạn có thể thay thế sleep 10cuộc gọi bằng

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

Điều này sẽ chờ một sự kiện tạo tệp xảy ra trong thư mục hiện tại, nhưng sẽ hết sau 10 giây. Bằng cách này, vòng lặp của bạn sẽ thoát ngay khi tên tệp đã cho xuất hiện (nếu nó xuất hiện).

Mã đầy đủ, với inotifywait(thay thế bằng sleep 10nếu bạn không muốn điều đó), có thể trông giống như

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

Với inotify, bạn gần như có thể thay thế toàn bộ vòng lặp. Chỉ cần kiểm tra xem tập tin có ở đó không, và nếu không, hãy chờ đợi trong 100 giây. Hầu như, vì tệp có thể được tạo ngay giữa thử nghiệm và inotify, và bạn sẽ ngủ đủ 100 giây trước khi hết giờ ...
ilkkachu

1
@ilkkachu Vâng, đó là một ý tưởng tốt, nhưng ở đây tôi chỉ sử dụng inotifywaitnhư là một thay thế thả vào cho sleep.
Kusalananda

8

Nếu số lượng không phải là một biến, bạn có thể sử dụng mở rộng dấu ngoặc:

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

Nếu số lượng là một biến bạn có thể sử dụng seqlệnh:

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

Tôi chỉ muốn lặp nếu tập tin không được tìm thấy (tối đa 10 lần). Nếu tìm thấy hãy nói lần thứ 3 rồi thoát thành công
Rocky86

@ Rocky86: Điều này không mâu thuẫn với giải pháp được đề xuất bởi xenoid. Không ai bắt bạn phải tính đến cuối ....
user1934428

Tôi thích cái này$(seq $count)
Công nhân

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

mặc dù test -e file && exitlinh hoạt hơn


Tại sao dấu chấm hỏi? Lưu ý rằng hành vi cho các khối trong mục tiêu chuyển hướng khác nhau giữa các vỏ.
Stéphane Chazelas

2
Lưu ý rằng nó có tác dụng phụ khi mở tệp, ví dụ như fifos có thể khá tệ (tệ hơn với symlink đến / dev / watchdog trên Linux chẳng hạn)
Stéphane Chazelas

Ngay cả ở Bash, nơi điều này sẽ tìm kiếm một tệp giống như exists1vậy, nó vẫn in một loạt lỗi nếu / khi không tìm thấy tệp phù hợp. (Ngoài ra, nó có lỗi nếu có nhiều kết quả khớp.) Bất kỳ shell nào khác mà tôi đã kiểm tra dường như đều có lỗi trong mọi trường hợp ...
ilkkachu

@ikkachu - vâng. đó là một vấn đề nếu lỗi xảy ra, tập lệnh báo cáo. nếu stderr nên bị triệt tiêu, triệt tiêu nó done 2<>/dev/null. Điều đó bashcó kịch bản không? tôi nghĩ rằng nó chỉ -iảnh hưởng đến bối cảnh đó. Tuy nhiên, exists?nhiều như một tên phụ như file. nhưng vâng, tôi ghét trích dẫn trong chuyển hướng - nếu vít quá nhiều.
mikeerv

@ Stéphane - không có lý do, thực sự. nhưng vâng, fifos, không thể đọc được ... đó là lý do tại sao tôi lưu ý test -e.
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.