Циклы и конструкции

Конструкция for...in предназначена для упрощения выполнения некоторых действий для группы значений или файлов, особенно при универсализации файловых имен, т.е. замене реальных символов в имени и расширении универсальными (например, "*" и "?") с целью формирования целых списков имен файлов. Шаблон *.sh в приведенном ниже цикле for позволяет обработать целый список совпадающих с ним (шаблоном) имен файлов из текущего каталога. Оператор for, проходя по этому списку, по очереди присваивает имя каждого файла переменной $file.

#!/bin/bash
suffix=BACKUP--`date +%Y%m%d-%H%M`
for script in *.sh; do
newname="$script.$suffix"
echo "Copying $script to $newname..."
cp $script $newname
done

Результат выполнения этого сценария таков:

$ sh forexample
Copying rhel.sh to rhel.sh.BACKUP--20091210-1708...
Copying sles.sh to sles.sh.BACKUP--20091210-1708...

В раскрытии имени файла все работает в точном соответствии с тем, как написано в командной строке. Другими словами, сначала имя файла раскрывается (т.е. шаблон заменяется существующим именем), а затем уже обрабатывается интерпретатором в развернутом виде.

Аналогично можно ввести имена файла статически, как показано в командной строке:

for script in rosa.sh postinst.sh; do

В действительности любой список имен, содержащих пробельные символы (включая содержимое переменной), обрабатывается как объект циклической конструкции for...in.

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

for (( i=0 ; i < $CPU_COUNT ; i++ )) ; do
CPU_LIST="$CPU_LIST $i"
done

На примере следующего сценария иллюстрируется bash-цикл while, который часто применяется для обработки аргументов командной строки и чтения строк файла:

#!/bin/bash
ехес 0<$1
counter=l
while read line; do
echo "$counter: $line"
$((counter++))
done

Результат выполнения этого сценария:

rosa$ sh whileexainple /etc/passwd
1: root:х:0:0:Superuser:/root:/bin/bash
2: bin:x:l:l:bin:/bin:/bin/bash
3: daemon:x:2:2:Daemon:/sbin:/bin/bash

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

Оператор read в конструкции while на самом деле является встроенным в оболочку, но действует подобно внешней команде. Внешние команды можно также помещать в конструкцию while. Цикл while в такой форме завершится при условии, если внешняя команда возвратит ненулевое значение кода завершения.

Конструкция $((counter++)) обозначает вычисление выражения. Кроме того, оно делает необязательным использование символа "$" для обозначения имен переменных. Удвоенный знак "++" – это оператор постинкремента, знакомый, например, по языку С. Он возвращает значение переменной, с которой он связан, но также увеличивает на 1 это значение.

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

while read line; do
echo "$((counter++)) : $line"
done