Як повторити цикл n разів у Bash


9

Я маю нижче такий сценарій, як:

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

Це дуже основна особливість снарядів. Ви навіть це досліджували?
Пешке

Так. Але не отримувати очікуваного виходу з мого коду. Також хочеться писати якомога
коротше

1
@Peschke, ну, їм потрібно хоч би що, три основні функції (циклі, умовні умови, тестування файлу, виривання з циклу). Принаймні, питання цілком зрозуміле, як воно є. Хоча він міг би містити ескіз того, що намагався Роккі, але тоді хтось все-таки переписав би його у відповідях. ;)
ilkkachu

Відповіді:


9

Існує багато способів зробити цю петлю.

З ksh93синтаксисом (також підтримується zshі bash):

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

Для будь-якої оболонки, схожої на POSIX:

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

Обидві петлі сплять по 10 секунд у кожній ітерації, перш ніж знову перевірити існування файлу.

Після завершення циклу вам доведеться перевірити наявність файлу в останній раз, щоб з’ясувати, чи завершився цикл через 10 разів запуску або через файл, який з'явився.

Якщо ви хочете, і якщо у вас є доступ до інструментів inotify, ви можете замінити sleep 10дзвінок на

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

Це зачекає, коли в поточному каталозі відбудеться подія створення файлу, але очікується час через 10 секунд. Таким чином, ваш цикл вийшов би, як тільки з'явилося дане ім'я файлу (якщо воно з’явилося).

Повний код з inotifywait(замінити на, sleep 10якщо ви цього не хочете) може виглядати приблизно так

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

Інотифікувавшись, ви могли майже замінити всю петлю. Просто перевірте, чи є файл, а якщо ні, інотифікуйте на 100 секунд. Майже, оскільки файл можна було створити саме між тестом та інотифікованим, і ви спали б цілих 100 секунд до вичерпання часу ...
ilkkachu

1
@ilkkachu Так, це гарна ідея, але тут я просто використовую inotifywaitяк заміну для спаду sleep.
Кусалаланда

8

Якщо кількість не є змінною, ви можете використовувати розширення дужок:

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

Якщо count є змінною, ви можете використовувати seqкоманду:

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

Я хочу зробити цикл лише в тому випадку, якщо файл не знайдено (максимум 10 разів). Якщо знайдемо, скажімо, 3-й раз, тоді успішно вийдіть
Rocky86,

@ Rocky86: Це не суперечить рішенню, запропонованому ксеноїдом. Ніхто не змушує вас рахувати до кінця ....
user1934428

Мені це подобається$(seq $count)
Робітниця

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

хоча test -e file && exitє більш гнучким


Чому знак питання? Зауважте, що поведінка для глобусів у цілі переадресації різниться між оболонками.
Стефан Шазелас

2
Зауважте, що у нього є побічний ефект відкриття файлу, який, наприклад, для фіфоса, може бути дуже поганим (що ще гірше, наприклад, з посиланням на / dev / сторожовий на Linux, наприклад)
Stéphane Chazelas

Навіть у Bash, де цей файл шукає подібний exists1або такий файл , він все ще видає купу помилок, якщо / коли відповідний файл не знайдений. (Крім того, це помилки, якщо є декілька збігів.) Будь-яка інша оболонка, яку я протестував, здається, в будь-якому випадку дає помилки ...
ilkkachu

@ikkachu - так. в чомусь справа. якщо помилка трапиться, сценарій повідомляє. якщо стридер повинен бути придушений, придушити його done 2<>/dev/null. це bashробить сценарій? Я думав, що це лише випливає в -iнетерактивному контексті. все-таки exists?є стільки ж, скільки і назва наповнювача file. але так, я ненавиджу цитувати переспрямовування - якщо гвинти так сильно вгору.
mikeserv

@ Stéphane - насправді немає причини. але так, фіфос, нечитабельні ... ось чому я зазначив test -e.
mikeserv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.