Одно из основных правил системного администрирования можно выразить так: если вам нужно часто делать одно и то же, напишите сценарий, и пусть он делает эту работу за вас. Если вам необходимо выполнять какое-то действие внутри сценария несколько раз, то вам стоит воспользоваться циклами. В GNU Bash вы можете создавать циклы при помощи конструкций for, while и until.
Если вы когда-нибудь интересовались программированием,то, скорее всего, вы уже знакомы с этими конструкциями. Если же вы, подобно мне, изучаете Bash, не имея за плечами опыта программирования, использование циклов может оказаться не достаточно очевидным для понимания. Начнём с определения различий между различными типами циклов, а затем перейдём к примерам.
Цикл for предназначен для повторения действий до тех пор, пока они все не будут выполнены. Представьте, например, что у вас есть каталог с изображениями, и вам необходимо преобразовать их из одного формата в другой. Вы можете использовать цикл forсовместно с программой convert из пакета ImageMagick (или какой-либо другой программой), например, для того, чтобы преобразовать изображения из формата JPEG в формат PNG. Или, например, вам может понадобиться преобразовать множество звуковых файлов из MP3 в OGG Vorbis.
Цикл while используется для повторения действий пока выполняется (является истинным) какое-то условие. Цикл until работает несколько по другому: он выполняет действие до тех пор, пока не выполнится условие. Так, например, вы можете счётчик и выполнять действиедо тех пор, пока его значение не достигнет 10. Рассмотрим это более подробно на примерах.
Цикл while используется для повторения действий пока выполняется (является истинным) какое-то условие. Цикл until работает несколько по другому: он выполняет действие до тех пор, пока не выполнится условие. Так, например, вы можете счётчик и выполнять действиедо тех пор, пока его значение не достигнет 10. Рассмотрим это более подробно на примерах.
Циклы for
Начнём с цикла 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, чтобы удалять файлы, а не создавать их. Просто, не так ли?
По мотивам Linux.Com