Як повторити цикл 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.