• Логическое и в цикле while bash. Почему цикл for не выполняется в каталоге. Пример: поиск исполняемых файлов

    for VAR in 1 2 3...N do done или в одну строку: for VAR in 1 2 3...N; do ; done
    В переменную допускается подставлять как числовые значения, так и ASCII символы.
    Пример: $ for i in 1 2 A B Abc ; do echo $i; done 1 2 A B Abc Пример перечисления в переменную файлов по "маске" для перекодирования видео: for i in *.avi; do ; done

    2. Подстановка результатов выполнения другой команды

    for VAR in $(); do ; done
    Пример использования результатов команды seq: for i in $(seq [КЛЮЧ]); do echo $i; done $ for i in $(seq 3); do echo $i; done 1 2 3 $ for i in $(seq 3 5); do echo $i; done 3 4 5 $ for i in $(seq 2 2 6); do echo $i; done 2 4 6 Пример использования результатов команды ls: $ for i in $(ls /$HOME/Video); do echo $i; done 001.avi 002.avi 003.avi

    3. Подстановка используя Си-стиль (C-style)

    for ((EXPR1; EXPR2; EXPR3)) do <список команд> done for ((i=1; i<=3 ; i++)); do echo $i; done $ for ((i=1; i<=3 ; i++)); do echo $i; done 1 2 3 Подробнее о применении C-style в Bash

    4. Перечисление при помощи фигурных скобок {..}

    Применение синтаксиса {START..END} поддерживается начиная с bash version 3.0+ , а начиная с bash version 4.0+ поддерживается синтаксис {START..END..INCREMENT} :

    for VAR in {..} do done или for VAR in {....} do done Примеры: $ for i in {1..3}; do echo $i; done 1 2 3 или $ for i in {4..8..2}; do echo $i; done 4 6 8 Отсчёт возможен как на приращение, так и на уменьшение значений: $ for i in {6..-4..3}; do echo $i; done 6 3 0 -3

    5. Подстановка параметров (in "$@")

    Выполняет команды для каждого параметра, который был передан сценарию. for VAR in $@ do done или в одну строку: for VAR in $@; do ; done
    Так если создать скрипт test.sh #!/bin/sh for VAR in $@ do echo $VAR done то при запуске его с параметрами: $ ./test.sh param1 param2 param3 param1 param2 param3 Часть in $@ можно опускать. Тогда скрипт test.sh перепишется: #!/bin/sh for VAR do echo $VAR done
    Приведу пару примеров (с in и без): $ function FUNC_1 { for VAR in $@; do echo $VAR; done; } $ FUNC_1 param1 param2 param3 param1 param2 param3 $ function FUNC_2 { for VAR; do echo $VAR; done; } $ FUNC_2 param1 param2 param3 param1 param2 param3

    6. Применение continue и break в цикле for

    Для всех вышеперечисленных конструкций возможно использовать команды "continue" для перехода к следующему элементу цикла или "break" для выхода из цикла.

    Пример (завершить при i=6 и не выполнять при i=3 и i=5): for i in {1..8}; do if [ $i -eq 6 ]; then break; fi if [ $i -eq 3 ] || [ $i -eq 5 ]; then continue; fi echo $i done Результат выполнения: $ $ for i in {1..8}; do \ > if [ $i -eq 6 ]; then break; fi; \ > if [ $i -eq 3 ] || [ $i -eq 5 ]; then continue; fi; \ > echo $i; \ > done 1 2 4

    Внимание: в посте спрятана выгода!

    Циклы for

    Оболочка bash поддерживает циклы for , которые позволяют организовывать перебор последовательностей значений. Вот какова базовая структура таких циклов:

    For var in list do команды done

    В каждой итерации цикла в переменную var будет записываться следующее значение из списка list . В первом проходе цикла, таким образом, будет задействовано первое значение из списка. Во втором - второе, и так далее - до тех пор, пока цикл не дойдёт до последнего элемента.

    Перебор простых значений

    Пожалуй, самый простой пример цикла for в bash-скриптах - это перебор списка простых значений:

    #!/bin/bash for var in first second third fourth fifth do echo The $var item done

    Ниже показаны результаты работы этого скрипта. Хорошо видно, что в переменную $var последовательно попадают элементы из списка. Происходит так до тех пор, пока цикл не дойдёт до последнего из них.



    Простой цикл for

    Обратите внимание на то, что переменная $var сохраняет значение при выходе из цикла, её содержимое можно менять, в целом, работать с ней можно как с любой другой переменной.

    Перебор сложных значений

    В списке, использованном при инициализации цикла for , могут содержаться не только простые строки, состоящие из одного слова, но и целые фразы, в которые входят несколько слов и знаков препинания. Например, всё это может выглядеть так:

    #!/bin/bash for var in first "the second" "the third" "I’ll do it" do echo "This is: $var" done

    Вот что получится после того, как этот цикл пройдётся по списку. Как видите, результат вполне ожидаем.



    Перебор сложных значений
    TNW-CUS-FMP - промо-код на 10% скидку на наши услуги, доступен для активации в течение 7 дней"

    Инициализация цикла списком, полученным из результатов работы команды

    Ещё один способ инициализации цикла for заключается в передаче ему списка, который является результатом работы некоей команды. Тут используется подстановка команд для их исполнения и получения результатов их работы.

    #!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" done

    В этом примере задействована команда cat , которая читает содержимое файла. Полученный список значений передаётся в цикл и выводится на экран. Обратите внимание на то, что в файле, к которому мы обращаемся, содержится список слов, разделённых знаками перевода строки, пробелы при этом не используются.



    Цикл, который перебирает содержимое файла

    Тут надо учесть, что подобный подход, если ожидается построчная обработка данных, не сработает для файла более сложной структуры, в строках которого может содержаться по несколько слов, разделённых пробелами. Цикл будет обрабатывать отдельные слова, а не строки.

    Что, если это совсем не то, что нужно?

    Разделители полей

    Причина вышеописанной особенности заключается в специальной переменной окружения, которая называется IFS (Internal Field Separator) и позволяет указывать разделители полей. По умолчанию оболочка bash считает разделителями полей следующие символы:

    • Пробел
    • Знак табуляции
    • Знак перевода строки

    Если bash встречает в данных любой из этих символов, он считает, что перед ним - следующее самостоятельное значение списка.

    Для того, чтобы решить проблему, можно временно изменить переменную среды IFS . Вот как это сделать в bash-скрипте, если исходить из предположения, что в качестве разделителя полей нужен только перевод строки:

    IFS=$"n"

    После добавления этой команды в bash-скрипт, он будет работать как надо, игнорируя пробелы и знаки табуляции, считая разделителями полей лишь символы перевода строки.

    #!/bin/bash file="/etc/passwd" IFS=$"n" for var in $(cat $file) do echo " $var" done

    Если этот скрипт запустить, он выведет он именно то, что от него требуется, давая, в каждой итерации цикла, доступ к очередной строке, записанной в файл.



    Построчный обход содержимого файла в цикле for

    Разделителями могут быть и другие символы. Например, выше мы выводили на экран содержимое файла /etc/passwd . Данные о пользователях в строках разделены с помощью двоеточий. Если в цикле нужно обрабатывать подобные строки, IFS можно настроить так:

    Обход файлов, содержащихся в директории

    Один из самых распространённых вариантов использования циклов for в bash-скриптах заключается в обходе файлов, находящихся в некоей директории, и в обработке этих файлов.

    Например, вот как можно вывести список файлов и папок:

    #!/bin/bash for file in /home/likegeeks/* do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a file" fi done

    Оболочка bash поддерживает циклы for , которые позволяют организовывать перебор последовательностей значений. Вот какова базовая структура таких циклов:

    For var in list do команды done
    В каждой итерации цикла в переменную var будет записываться следующее значение из списка list . В первом проходе цикла, таким образом, будет задействовано первое значение из списка. Во втором - второе, и так далее - до тех пор, пока цикл не дойдёт до последнего элемента.

    Перебор простых значений

    Пожалуй, самый простой пример цикла for в bash-скриптах - это перебор списка простых значений:

    #!/bin/bash for var in first second third fourth fifth do echo The $var item done
    Ниже показаны результаты работы этого скрипта. Хорошо видно, что в переменную $var последовательно попадают элементы из списка. Происходит так до тех пор, пока цикл не дойдёт до последнего из них.


    Простой цикл for

    Обратите внимание на то, что переменная $var сохраняет значение при выходе из цикла, её содержимое можно менять, в целом, работать с ней можно как с любой другой переменной.

    Перебор сложных значений

    В списке, использованном при инициализации цикла for , могут содержаться не только простые строки, состоящие из одного слова, но и целые фразы, в которые входят несколько слов и знаков препинания. Например, всё это может выглядеть так:

    #!/bin/bash for var in first "the second" "the third" "I’ll do it" do echo "This is: $var" done
    Вот что получится после того, как этот цикл пройдётся по списку. Как видите, результат вполне ожидаем.


    Перебор сложных значений
    TNW-CUS-FMP - промо-код на 10% скидку на наши услуги, доступен для активации в течение 7 дней"

    Инициализация цикла списком, полученным из результатов работы команды

    Ещё один способ инициализации цикла for заключается в передаче ему списка, который является результатом работы некоей команды. Тут используется подстановка команд для их исполнения и получения результатов их работы.

    #!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" done
    В этом примере задействована команда cat , которая читает содержимое файла. Полученный список значений передаётся в цикл и выводится на экран. Обратите внимание на то, что в файле, к которому мы обращаемся, содержится список слов, разделённых знаками перевода строки, пробелы при этом не используются.


    Цикл, который перебирает содержимое файла

    Тут надо учесть, что подобный подход, если ожидается построчная обработка данных, не сработает для файла более сложной структуры, в строках которого может содержаться по несколько слов, разделённых пробелами. Цикл будет обрабатывать отдельные слова, а не строки.

    Что, если это совсем не то, что нужно?

    Разделители полей

    Причина вышеописанной особенности заключается в специальной переменной окружения, которая называется IFS (Internal Field Separator) и позволяет указывать разделители полей. По умолчанию оболочка bash считает разделителями полей следующие символы:
    • Пробел
    • Знак табуляции
    • Знак перевода строки
    Если bash встречает в данных любой из этих символов, он считает, что перед ним - следующее самостоятельное значение списка.

    Для того, чтобы решить проблему, можно временно изменить переменную среды IFS . Вот как это сделать в bash-скрипте, если исходить из предположения, что в качестве разделителя полей нужен только перевод строки:

    IFS=$"\n"
    После добавления этой команды в bash-скрипт, он будет работать как надо, игнорируя пробелы и знаки табуляции, считая разделителями полей лишь символы перевода строки.

    #!/bin/bash file="/etc/passwd" IFS=$"\n" for var in $(cat $file) do echo " $var" done
    Если этот скрипт запустить, он выведет он именно то, что от него требуется, давая, в каждой итерации цикла, доступ к очередной строке, записанной в файл.


    Построчный обход содержимого файла в цикле for

    Разделителями могут быть и другие символы. Например, выше мы выводили на экран содержимое файла /etc/passwd . Данные о пользователях в строках разделены с помощью двоеточий. Если в цикле нужно обрабатывать подобные строки, IFS можно настроить так:

    Обход файлов, содержащихся в директории

    Один из самых распространённых вариантов использования циклов for в bash-скриптах заключается в обходе файлов, находящихся в некоей директории, и в обработке этих файлов.

    Например, вот как можно вывести список файлов и папок:

    #!/bin/bash for file in /home/likegeeks/* do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a file" fi done
    Если вы разобрались с предыдущим материалом из этой серии статей, вам должно быть понятно устройство конструкции if-then , а так же то, как отличить файл от папки. Если вам сложно понять вышеприведённый код, перечитайте этот материал.

    Вот что выведет скрипт.


    Вывод содержимого папки

    Обратите внимание на то, как мы инициализируем цикл, а именно - на подстановочный знак «*» в конце адреса папки. Этот символ можно воспринимать как шаблон, означающий: «все файлы с любыми именами». он позволяет организовать автоматическую подстановку имён файлов, которые соответствуют шаблону.

    При проверке условия в операторе if , мы заключаем имя переменной в кавычки. Сделано это потому что имя файла или папки может содержать пробелы.

    Циклы for в стиле C

    Если вы знакомы с языком программирования C, синтаксис описания bash-циклов for может показаться вам странным, так как привыкли вы, очевидно, к такому описанию циклов:

    For (i = 0; i < 10; i++) { printf("number is %d\n", i); }
    В bash-скриптах можно использовать циклы for , описание которых выглядит очень похожим на циклы в стиле C, правда, без некоторых отличий тут не обошлось. Схема цикла при подобном подходе выглядит так:

    For ((начальное значение переменной; условие окончания цикла; изменение переменной))
    На bash это можно написать так:

    For ((a = 1; a < 10; a++))
    А вот рабочий пример:

    #!/bin/bash for ((i=1; i <= 10; i++)) do echo "number is $i" done
    Этот код выведет список чисел от 1 до 10.

    Работа цикла в стиле C

    Цикл while

    Конструкция for - не единственный способ организации циклов в bash-скриптах. Здесь можно пользоваться и циклами while . В таком цикле можно задать команду проверки некоего условия и выполнять тело цикла до тех пор, пока проверяемое условие возвращает ноль, или сигнал успешного завершения некоей операции. Когда условие цикла вернёт ненулевое значение, что означает ошибку, цикл остановится.

    Вот схема организации циклов while
    while команда проверки условия
    do
    другие команды
    done

    Взглянем на пример скрипта с таким циклом:

    #!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
    На входе в цикл проверяется, больше ли нуля переменная $var1 . Если это так, выполняется тело цикла, в котором из значения переменной вычитается единица. Так происходит в каждой итерации, при этом мы выводим в консоль значение переменной до его модификации. Как только $var1 примет значение 0, цикл прекращается.

    Результат работы цикла while

    Если не модифицировать переменную $var1 , это приведёт к попаданию скрипта в бесконечный цикл.

    Вложенные циклы

    В теле цикла можно использовать любые команды, в том числе - запускать другие циклы. Такие конструкции называют вложенными циклами:

    #!/bin/bash for ((a = 1; a <= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
    Ниже показано то, что выведет этот скрипт. Как видно, сначала выполняется первая итерация внешнего цикла, потом - три итерации внутреннего, после его завершения снова в дело вступает внешний цикл, потом опять - внутренний.

    Вложенные циклы

    Обработка содержимого файла

    Чаще всего вложенные циклы используют для обработки файлов. Так, внешний цикл занимается перебором строк файла, а внутренний уже работает с каждой строкой. Вот, например, как выглядит обработка файла /etc/passwd:

    #!/bin/bash IFS=$"\n" for entry in $(cat /etc/passwd) do echo "Values in $entry –" IFS=: for value in $entry do echo " $value" done done
    В этом скрипте два цикла. Первый проходится по строкам, используя в качестве разделителя знак перевода строки. Внутренний занят разбором строк, поля которых разделены двоеточиями.

    Обработка данных файла

    Такой подход можно использовать при обработке файлов формата CSV, или любых подобных файлов, записывая, по мере надобности, в переменную окружения IFS символ-разделитель.

    Управление циклами

    Возможно, после входа в цикл, нужно будет остановить его при достижении переменной цикла определённого значения, которое не соответствует изначально заданному условию окончания цикла. Надо ли будет в такой ситуации дожидаться нормального завершения цикла? Нет конечно, и в подобных случаях пригодятся следующие две команды:
    • break
    • continue

    Команда break

    Эта команда позволяет прервать выполнение цикла. Её можно использовать и для циклов for , и для циклов while:

    #!/bin/bash for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Number: $var1" done
    Такой цикл, в обычных условиях, пройдётся по всему списку значений из списка. Однако, в нашем случае, его выполнение будет прервано, когда переменная $var1 будет равна 5.

    Досрочный выход из цикла for

    Вот - то же самое, но уже для цикла while:

    #!/bin/bash var1=1 while [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] then break fi echo "Iteration: $var1" var1=$(($var1 + 1)) done
    Команда break , исполненная, когда значение $var1 станет равно 5, прерывает цикл. В консоль выведется то же самое, что и в предыдущем примере.

    Команда continue

    Когда в теле цикла встречается эта команда, текущая итерация завершается досрочно и начинается следующая, при этом выхода из цикла не происходит. Посмотрим на команду continue в цикле for:

    #!/bin/bash for ((var1 = 1; var1 < 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
    Когда условие внутри цикла выполняется, то есть, когда $var1 больше 5 и меньше 10, оболочка исполняет команду continue . Это приводит к пропуску оставшихся в теле цикла команд и переходу к следующей итерации.

    Команда continue в цикле for

    Обработка вывода, выполняемого в цикле

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

    Например, вместо того, чтобы показывать на экране то, что выводится в цикле, можно записать всё это в файл или передать ещё куда-нибудь:

    #!/bin/bash for ((a = 1; a < 10; a++)) do echo "Number is $a" done > myfile.txt echo "finished."
    Оболочка создаст файл myfile.txt и перенаправит в этот файл вывод конструкции for . Откроем файл и удостоверимся в том, что он содержит именно то, что ожидается.

    Перенаправление вывода цикла в файл

    Пример: поиск исполняемых файлов

    Давайте воспользуемся тем, что мы уже разобрали, и напишем что-нибудь полезное. Например, если надо выяснить, какие именно исполняемые файлы доступны в системе, можно просканировать все папки, записанные в переменную окружения PATH . Весь арсенал средств, который для этого нужен, у нас уже есть, надо лишь собрать всё это воедино:

    #!/bin/bash IFS=: for folder in $PATH do echo "$folder:" for file in $folder/* do if [ -x $file ] then echo " $file" fi done done
    Такой вот скрипт, небольшой и несложный, позволил получить список исполняемых файлов, хранящихся в папках из PATH .

    Поиск исполняемых файлов в папках из переменной PATH

    Итоги

    Сегодня мы поговорили о циклах for и while в bash-скриптах, о том, как их запускать, как ими управлять. Теперь вы умеете обрабатывать в циклах строки с разными разделителями, знаете, как перенаправлять данные, выведенные в циклах, в файлы, как просматривать и анализировать содержимое директорий.

    Если предположить, что вы - разработчик bash-скриптов, который знает о них только то, что изложено в первой части этого цикла статей, и в этой, второй, то вы уже вполне можете написать кое-что полезное. Впереди - третья часть, разобравшись с которой, вы узнаете, как передавать bash-скриптам параметры и ключи командной строки, и что с этим всем делать.

    Одно из основных правил системного администрирования можно выразить так: если вам нужно часто делать одно и то же, напишите сценарий, и пусть он делает эту работу за вас. Если вам необходимо выполнять какое-то действие внутри сценария несколько раз, то вам стоит воспользоваться циклами . В GNU Bash вы можете создавать циклы при помощи конструкций for , while и until .

    Если вы когда-нибудь интересовались программированием,то, скорее всего, вы уже знакомы с этими конструкциями. Если же вы, подобно мне, изучаете Bash , не имея за плечами опыта программирования, использование циклов может оказаться не достаточно очевидным для понимания. Начнём с определения различий между различными типами циклов, а затем перейдём к примерам.

    Цикл for предназначен для повторения действий до тех пор, пока они все не будут выполнены. Представьте, например, что у вас есть каталог с изображениями, и вам необходимо преобразовать их из одного формата в другой. Вы можете использовать цикл for совместно с программой convert из пакета ImageMagick (или какой-либо другой программой), например, для того, чтобы преобразовать изображения из формата JPEG в формат PNG. Или, например, вам может понадобиться преобразовать множество звуковых файлов из MP3 в OGG Vorbis .

    Цикл while используется для повторения действий пока выполняется (является истинным ) какое-то условие. Цикл until работает несколько по другому: он выполняет действие до тех пор , пока не выполнится условие. Так, например, вы можете счётчик и выполнять действие до тех пор , пока его значение не достигнет 10. Рассмотрим это более подробно на примерах.

    Начнём с цикла for . Его формат таков:

    For i in $(command); do command $i; done

    Если вы используете цикл for в скрипте, лучше отформатировать его так:

    #!/bin/bash for i in $(command); do command $i done

    Так, например, если вам нужно сделать резервные копии всех HTML-файлов, находящихся в каталоге, вы можете использовать следующую команду:

    For i in $(ls *html); do cp $i $i.bak; done

    Здесь создаётся локальная переменная $i , выполняется команда ls *html , результаты выполнения которой и будут являться данными, инициализирующими значение переменной $i при каждой итерации цикла (в нашем примере это будет список файлов, возвращаемый командой ls , по одному за каждую итерацию). Далее, выполняется команда cp , которой среди параметров передаётся переменная $i .

    Кто-то может спросить, обязательно ли использовать букву «i» в качестве имени переменной? Нет. Вы можете использовать любое корректное для Bash имя переменной. Конечно же, в сценариях лучше использовать более осмысленные имена переменных, вроде $input или $html .

    Я привёл очень краткий и простой пример использования цикла for . Вместо команды, выполняющейся в блоке do ,используйте echo для того, чтобы увидеть параметры, передаваемые ей. Это очень полезная практика на стадии тестирования скриптов, а также хороший способ помочь вам более подробно разобраться с работой for .

    while и until

    Рассмотрим теперь конструкции while и until . Также, мы немного воспользуемся условными выражениями bash . В нашем примере мы будем использовать их для того, чтобы определять, например, является ли значение переменной большим или меньшим, чем число X; существует ли файл и является ли он каталогом. Вы также можете использовать условные выражения для определения, например, доступности файла для чтения или присутствия в его правах доступа GID-бита.

    Давайте попробуем сделать что-нибудь простое, например, создадим несколько пустых файлов. В жизни это вряд ли вам пригодится, но в качестве примера — самое оно.

    #!/bin/bash i=0 while [ $i -lt 22 ] do touch $i i=$[$i+1] done

    Этот скрипт создаст 22 файла с именами от 0 до 21. Цикл будет работать до тех пор, пока значение переменной $i меньше (-lt ) 22.

    Теперь давайте избавимся от созданных файлов при помощи цикла until :

    #!/bin/bash i=0 until [ $i -eq 22 ] do rm $i i=$[$i+1] done

    Здесь мы заменили while на until , а в условном выражении заменили «меньше» (-lt ) на «равно» (-eq ). Таким образом, наш скрипт будет работать до тех пор, пока значение $i не достигнет 22. И вместо touch мы использовали rm , чтобы удалять файлы, а не создавать их. Просто, не так ли?

    На этой лекции мы продолжаем знакомиться с bash . Хочу напомнить, что мы рассматриваем те элементы bash , которые помогут нам понимать скрипты операционной системы. Такими элементами безусловно являются циклы и функции. Если кто-то изучал программирование, то трудностей с пониманием этих вопросов не возникнет.

    Цикл for

    Цикл for в bash имеет два вида. Рассмотрим сначала классический вариант for . Общий вид следующий:

    Между элементами for и in задается переменная, которая по очереди принимает значение из последовательности значений заданной между in и do . Между do и done находятся команды которые выполняются каждый раз когда переменная меняет свое значение. Цикл прекращает работу когда переменная примет последнее значение из последовательности. Значения в последовательности задаются через пробел.

    А вот практический пример:

    Последовательность значений можно задавать разными способами. Явно — как в примере выше, или с помощью других переменных, или с помощью специальных команд. Рассмотрим некоторые примеры. Так как значения задаются через пробел, то в качестве таких значений может быть любая переменная, которая содержит строку с пробелами:

    Результат будет таким же как и в первом примере.

    Если необходимо задать последовательность чисел, то можно воспользоваться командой seq и механизмом подстановки. Команда seq возвращает на экран последовательность числовых значений. Синтаксис прост и будет понятен из примера ниже:

    Результат:

    Вернемся ко второму виду for . Часто в скриптах можно встретить так называемый С-подобный вариант for , которых используется для циклов на основе чисел. Рассмотрим сразу пример:

    Цикл выполняется пока проверяемое в выражении условие верно. Как только выражение возвращает ложь выполнение цикла прекращается.

    Практический пример:

    #!/bin/bash
    i=1
    while [ $i -lt 7 ]
    do
    echo $i
    let i=i+1
    done

    В нашем примере проверяется, что переменная i меньше (-lt), числа 7 и если это так, то значение переменной выводится на экран. Выражение let i=i+1 , увеличивает переменную на единицу, снова происходит проверка и т.д. let говорит интерпретатору о том, что аргументы следует распознавать как числовые значения. Это строку можно было записать как let i++ (c-подобный вариант). При увеличении числа более чем на единицу можно записать так: let i+=2 — в этом случае i будет увеличиваться с шагом 2. Еще один вариант увеличения переменной это использование встроенного калькулятора (работает только с целыми числами). Доступ к калькулятору можно получить через двойные скобки: i=$(($i+1)) или через квадратные: i=$[$i+1] Пользоваться калькулятором можно и в командной строке:

    С циклами нужно быть аккуратными, чтобы не получить вариант бесконечного цикла. Кстати для отладки bash скриптов можно изменить первую строку на#!/bin/bash -x или запускать скрипт командой bash -x :

    igor@ubuntu:~/linux$ bash -x ./testfor.sh
    + i=1
    + ‘[‘ 1 -gt 5 ‘]’
    + echo i=1
    i=1
    + let i=i+1
    + ‘[‘ 2 -gt 5 ‘]’
    + echo i=2
    i=2
    + let i=i+1
    + ‘[‘ 3 -gt 5 ‘]’
    + echo i=3
    i=3
    + let i=i+1
    + ‘[‘ 4 -gt 5 ‘]’
    + echo i=4
    i=4
    + let i=i+1
    + ‘[‘ 5 -gt 5 ‘]’
    + echo i=5
    i=5
    + let i=i+1
    + ‘[‘ 6 -gt 5 ‘]’

    Обязательно потренируйтесь в написании небольших скриптов для закрепления понимания работы циклов вbash .

    Функции в bash

    Функции применяются в bash очень широко. Описываются функции двумя способами: с ключевым словомfunction , и без него.

    Первый способ:

    function имя_функции
    {
    тело функции
    }

    Второй способ:

    имя_функции ()
    {
    тело функции
    }

    Вызывается функция по имени в любом месте скрипта, но только после описания самой функции. Функции также можно передавать параметры, которые задаются через пробел после вызова (имени) функции. Рассмотрим пример скрипта bash :

    #!/bin/bash
    function primer
    {
    if [ $# -ne 0 ]
    then
    local a=1
    echo «Количество переданных параметров — $#»
    for i in $@
    do
    echo «$a-й параметр — $i»
    let a++
    done
    return 0
    else
    echo «Параметры не передавались»
    return 1
    fi
    }
    echo «Вызываем функцию с параметрами:»
    primer a b c
    echo $?
    echo «Вызываем функцию без параметров:»
    primer
    echo $?

    В данном примере задана функция с именем primer . Вызов функции с параметрами: primer a b c и без параметров: primer . В теле функции все конструкции вам должны быть знакомы, за исключением $# , $i и $@ .$# — возвращает количество параметров переданных функции. В нашем примере это будет число 3 .$@ возвращает все параметры одной строкой. В примере это будет a b c . А через $1 , $2 , $3 и т.д. можно обращаться к каждому параметру персонально. $? — содержит код выполнения последней команды. В нашем примере код выполнения функции.

    Функция может также возвращать числовое значение через ключевое слово return . Как правило возвращают 0, если функция выполнена без ошибок или отличное от нуля значение, если что-то пошло не так. В примере, в случае вызова функции с параметрами, идет возврат значения 0, а если функция вызывалась без параметров, то будет возврат кода 1.

    Все, что касается передачи параметров в функцию, работает точно так же и для скрипта. Скрипту точно также можно передавать параметры и точно также манипулировать ими при помощи $#, $@, $N . Из этой же категории и вариант — $0 — который возвращает имя команды запустившей скрипт. Если скрипт запускался по команде./script.sh , то echo $0 вернет значение ./script.sh , а если по команде /home/igor/linux/script.sh , то будет возвращено значение /home/igor/linux/script.sh .