Problem dotyczy testu, a nie snu (jak postawiono hipotezę w oryginalnym pytaniu). Najmniejsza możliwa poprawka może wyglądać następująco:
while ! test -f "/tmp/$1"; do
sleep 10
echo "Still waiting"
done
Pamiętaj składnię dla while
pętli:
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.
to znaczy, pierwszy argument dany while
, rozwijając pętlę, jest to polecenie; musi przestrzegać tych samych reguł składni, co każde inne polecenie powłoki.
-f
jest ważna jako argument do test
- komenda, która jest również dostępna pod nazwą [
, wymagające ]
jako ostatni argument stosowany w tej nazwie - ale to nie jest ważne jak polecenia w sobie - i gdy jest przekazywany jako część łańcucha, nie jest to nawet słowo powłoki, które może być przetwarzane jako pojedyncza nazwa polecenia lub argument.
Po uruchomieniu '(-f ! /tmp/$1)'
jako polecenia, w cudzysłowie powłoka szuka rzeczywistego polecenia o dokładnie tej nazwie (łącznie ze spacjami). Prawdopodobnie nie masz pliku o nazwie '/usr/bin/(-f ! /tmp/$1)'
w ścieżce PATH lub innym poleceniu o tej nazwie, więc zawsze zawiedzie - natychmiast zamknie pętlę while
.
Przy okazji - jeśli jesteś skłonny do kodu OS specyficzne, istnieją inne metody niż przy użyciu sleep
czekać na plik istnieć. Weźmy na przykład, inotifywait
z pakietu 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
o skorzystanie z interfejsu opartego inotify jest, że zwraca natychmiast po zmianie systemu plików, a nie ponosić narzut odpytywania (co może być szczególnie istotna jeśli zapobiega snu z systemu).
Nawiasem mówiąc, niektóre praktyczne Uwagi: (tzn. "/tmp/$1"
)
- Cytowanie ekspansji w nazwach zapobiega nazwy spacjami lub literowych przed rozwinięciem się w wielu różnych argumentów.
- Korzystanie
>&2
na echo
polecenia przeznaczona do logowania do spożycia przez ludzi utrzymuje stderr dostępny do spożycia programowej
let
służy do matematyki, nie przypisań ogólnego przeznaczenia.Jeśli chcesz użyć "$file"
, nic złego - ale przypisanie powinno być tylko file=$1
, bez poprzedzającego let
.
'' (...) ''jest STRING, który sprowadza się do' while true'. spróbuj 'while [! -f/tmp/$ 1]' lub podobnie. –
@MarcB, co? Nie "podczas gdy prawda" w ogóle; to 'while while false', ponieważ ten ciąg nie jest poprawnym poleceniem. Jeśli znajdował się w teście, * wtedy * może być. –
BTW, w przyszłości, należy rozważyć użycie 'bash -x yourscript' aby dowiedzieć się, co dzieje się w trakcie realizacji - w tym przypadku, że wykazały, że jechaliśmy prosto z' '(! -f/tmp/$ 1) "' to 'echo" Treść pliku $ 1: "', wykluczając tym samym problem z 'sleep' (ponieważ w ogóle nie był uruchamiany). –