2016-10-14 10 views
6

Tôi cần tạo tập lệnh bash để đợi tạo một tập tin. Kịch bản lệnh sẽ sử dụng lệnh ngủ bên trong một vòng lặp while để kiểm tra định kỳ một tệp cứ 10 giây một lần. In ra một tin nhắn trong khi chờ đợi. Hiển thị nội dung của tệp khi tệp được tạo. Dưới đây là những gì tôi đã cố gắng thực hiện và rõ ràng là nó không hoạt động. Tại thời điểm này, tôi không hoàn toàn chắc chắn làm thế nào để tiến hành.Đang đợi tạo một tập tin trong Bash

#!/bin/bash 
let file=$1 

while '(-f ! /tmp/$1)' 
do 
     sleep 10 
     echo "still waiting" 
done 

echo "Content of the file $1:" 
+0

''(...)'' là STRING, từ đó nhấn xuống thành 'while true'. thử 'while [! -f/tmp/$ 1]' hoặc tương tự. –

+1

@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. –

+1

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ả). –

Trả lời

11

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.
+2

Đối với người dùng Mac, bạn có thể sử dụng 'fswatch' thay vì' inotifywait': 'fswatch --event Created --event Updated" $ INPUT_DIR "' – Julian

Các vấn đề liên quan