Vấn đề ở đây là thử nghiệm, không phải là giấc ngủ (như câu hỏi ban đầu được đưa ra giả thuyết). Việc sửa chữa nhỏ nhất có thể có thể trông như sau:
while ! test -f "/tmp/$1"; do
sleep 10
echo "Still waiting"
done
Hãy ghi nhớ cú pháp cho một vòng lặp while
:
while: while COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
Đó là để nói, đối số đầu tiên trao cho while
, mở rộng vòng lặp, là một lệnh ; nó cần phải thực hiện theo các quy tắc cú pháp giống như bất kỳ lệnh shell nào khác.
-f
có giá trị như một cuộc tranh cãi để test
- một lệnh mà cũng có thể truy cập dưới tên [
, đòi hỏi một ]
như là đối số cuối cùng khi được sử dụng trong tên đó - nhưng nó không có giá trị như một lệnh trong và của chính nó - và khi được chuyển thành một phần của chuỗi, thậm chí không phải là từ vỏ mà có thể được phân tích cú pháp dưới dạng tên hoặc đối số lệnh riêng lẻ.
Khi bạn chạy '(-f ! /tmp/$1)'
làm lệnh, bên trong dấu ngoặc kép, vỏ sẽ tìm kiếm lệnh thực tế với tên chính xác (bao gồm dấu cách). Bạn có thể không có tệp có tên '/usr/bin/(-f ! /tmp/$1)'
trong PATH của bạn hoặc bất kỳ lệnh nào khác theo tên được tìm thấy, vì vậy nó sẽ luôn thất bại - thoát khỏi vòng lặp while
ngay lập tức.
Bằng cách này - nếu bạn sẵn sàng để làm cho mã của bạn OS-cụ thể, có những cách tiếp cận khác so với sử dụng sleep
chờ đợi cho một tập tin để tồn tại. Xem xét, ví dụ, inotifywait
, thuộc về gói inotify-tools
:
while ! test -f "/tmp/$1"; do
echo "waiting for a change to the contents of /tmp" >&2
inotifywait --timeout 10 --event create /tmp >/dev/null || {
(($? == 2)) && continue ## inotify exit status 2 means timeout expired
echo "unable to sleep with inotifywait; doing unconditional 10-second loop" >&2
sleep 10
}
done
Lợi ích của một giao diện inotify-based được rằng nó sẽ trả về ngay khi có sự thay đổi hệ thống tập tin, và không chịu bỏ phiếu trên không (mà có thể đặc biệt quan trọng nếu nó ngăn cản hệ thống ngủ).
Bằng cách này, một số lưu ý thực hành: (. Tức là "/tmp/$1"
)
- mở rộng Báo giá bằng tên tập tin ngăn chặn tên có khoảng trắng hoặc ký tự đại diện từ được mở rộng sang nhiều lập luận khác nhau.
- Sử dụng
>&2
trên echo
lệnh có nghĩa là để đăng nhập cho con người giữ stderr sẵn phục vụ tiêu dùng theo chương trình
let
được sử dụng cho toán, không có mục đích chung nhiệm vụ.Nếu bạn muốn sử dụng "$file"
, không có gì sai với điều đó - nhưng nhiệm vụ chỉ nên là file=$1
, không có trước let
.
''(...)'' là STRING, từ đó nhấn xuống thành 'while true'. thử 'while [! -f/tmp/$ 1]' hoặc tương tự. –
@MarcB, eh? Không phải là 'trong khi đúng '; đó là 'while false', vì chuỗi đó không phải là một lệnh hợp lệ. Nếu nó ở trong một thử nghiệm, * thì * nó có thể là ture. –
BTW, trong tương lai, hãy xem xét sử dụng 'bash -x yourscript' để tìm ra những gì đang xảy ra trong quá trình thực thi - trong trường hợp này, điều đó cho thấy chúng ta đang đi thẳng từ' '(-f!/Tmp/$ 1) ''to' echo' Nội dung của tệp $ 1: "', do đó loại trừ vấn đề với 'sleep' (vì nó không được chạy ở tất cả). –