2010-03-04 6 views
51

Я работаю над скриптом оболочки, который вносит определенные изменения в файл txt, только если он существует, однако этот тестовый цикл не работает, интересно, почему? Спасибо!Хотя цикл для проверки, существует ли файл в bash

while [ ! -f /tmp/list.txt ] ; 
do 
     sleep 2 
done 
+3

Я не могу сказать, что я удивлен; этот цикл не пытается ничего изменить. –

+0

Полу-двоеточие избыточно.Каким образом этот тестовый цикл не работает? Он будет итеративно спать в течение 2 секунд, пока файл /tmp/list.txt не будет существовать. –

+4

Работает для меня - цикл завершается, когда файл создается вне сценария. – 2010-03-04 14:14:15

ответ

78

Когда вы говорите «не работает», откуда вы знаете, что это не работает?

Вы могли бы попытаться выяснить, если файл существует на самом деле, добавив:

while [ ! -f /tmp/list.txt ] 
do 
    sleep 2 
done 
ls -l /tmp/list.txt 

Вы также можете убедиться, что вы используете Bash (или связанные) оболочки, набрав «эхо $ SHELL». Я думаю, что CSH и TCSH используют немного другую семантику для этого цикла.

+0

Почему вы используете проверку инвертированного файла? Не следует ли использовать [-f /tmp/list.txt] вместо этого? – valentt

+0

Какие существуют семантические различия? –

+1

@valentt Нет hew loop сказать буквально «пока файл НЕ существует, спать». Если вы удалите «NOT», цикл будет мгновенно разорвать –

-4

сделать это как этот

while true 
do 
    [ -f /tmp/list.txt ] && break 
    sleep 2 
done 
ls -l /tmp/list.txt 
40

Если у вас установлен Inotify-инструменты, вы можете сделать это:

file=/tmp/list.txt 
while [ ! -f "$file" ] 
do 
    inotifywait -qqt 2 -e create -e moved_to "$(dirname $file)" 
done 

Это уменьшает задержку, вносимую сон в то же время проверять каждые 2 секунды. Вы можете добавить больше событий, если будете ожидать, что они понадобятся.

+4

+1 для эффективности. Объединение со сном является уродливым. Для людей, не знающих inotifywait - это в пакетах inotify-tools. –

+6

Это чрезвычайно удобный инструмент. Для тех, кто задается вопросом, почему цикл, это дело с возможными условиями гонки между созданием и ожиданием, и потому что inotifywait имеет '--exclude', чтобы отфильтровать имена файлов, но не' --include', чтобы игнорировать все _except_ имя файла. Вышеприведенная команда должна использовать аргумент '-qq' вместо'> &/dev/null'. –

+0

t - это '--timeout', а не частота проверки, нет? Пункт inotifywait заключается в том, что нет опроса –

1

Я столкнулся с подобной проблемой, и это привело меня сюда, поэтому я просто хотел оставить свое решение для тех, кто испытывает то же самое.

Я обнаружил, что если бы я запустил cat /tmp/list.txt, файл был бы пуст, хотя я был уверен, что в файл сразу же помещается содержимое. Оказывается, если я положил sleep 1; непосредственно перед cat /tmp/list.txt, он работал, как ожидалось. Должна была быть задержка между временем создания файла и временем его написания или что-то в этом направлении.

Моего окончательный код:

while [ ! -f /tmp/list.txt ]; 
do 
    sleep 1; 
done; 
sleep 1; 
cat /tmp/list.txt; 

Надеется, что это помогает сохранить кому-то расстраивает полчаса!

2

У меня была та же проблема, поставьте! вне скобок;

while ! [ -f /tmp/list.txt ]; 
do 
    echo "#" 
    sleep 1 
done 

Кроме того, если вы добавите эхо в цикл, он скажет вам, попадаете ли вы в цикл или нет.

0

Как @ zane-hooper, у меня была аналогичная проблема с NFS. В параллельных/распределенных файловых системах отставание между созданием файла на одной машине и другой машиной, «видя» его, может быть очень большим, поэтому я могу подождать до полной минуты после создания файла до выхода цикла while (и существует также последействие «видеть» уже удаленный файл).

Это создает иллюзию, что сценарий «не работает», в то время как на самом деле это файловая система, которая бросает мяч.

Это заняло у меня некоторое время, чтобы понять, надеюсь, что это кому-то поможет.

PS Это также вызывает раздражающее количество ошибок «Stale file handler».

Смежные вопросы