Конструкции


if

Можно и так:

if python -c "exit(0)"; then echo OK; else echo FAIL; fi

если удобнее, if можно записать в несколько строк:

if команда
then
  тело
fi
if команда
then
  тело
else
  иначе_тело
fi

Выполнит или не выполнит тело в зависимости от того, завершилась команда с кодом возврата 0 (выполнит) или другим (не выполнит).


for

В shell есть циклы for такого формата:

for var_name in набор значений
do
  тело цикла
done

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

for i in 1 2 3; do echo $i; done
## вывод
1
2
3

Аргументы подаются так же, как и в любую другую команду, то есть можно, например, направить туда вывод чего-нибудь.


for

Аналог ls для бедных:

for i in *; do printf "%s\n" "$i"; done

Аналог for i in range(11): из Python.

for i in $(seq 0 10);
  do                 
    echo $i;         
    echo $((10-i));  
  done

while

Также имеются циклы while:

while команда
do
  тело цикла
done

Тело цикла будет выполняться, пока команда не вернёт код ошибки, отличный от нуля.


while

Например, с помощью test будет ждать, когда появится файл x:

while ! test -f x; do sleep 1; done 

здесь сначала исполняем команду test, если код возврата отличен от 0 (т.е. файл не сущесвтует), то ! test будет интерпретирован как 0, поэтому будем ожидать через sleep 1.

Или можно организовать чтение с помощью read:

printf "1 2\n3 4\n" | while read a b; do \
  echo "$a;$b"     \
done

case

case <переменная> in
    образец1)
        команды для образца1;;
    образец2)
        команды для образца2;;
    *)
        команды по умолчанию;;
esac

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


Пример

case $1 in
    start)
        echo "Запуск процесса";;
    stop)
        echo "Остановка процесса";;
    *)
        echo "Использование: $0 {start|stop}";;
esac

Этот скрипт принимает аргумент $1 и сопоставляет его с start или stop. В зависимости от аргумента выполняются соответствующие команды.

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


test

test(1) — полезная команда, с помощью которой можно проверять, например, существует ли какой-то файл, не директория ли это, равны ли две строки и так далее.

У этой команды есть синоним [ с дополнительным требованием, что вызов [ нужно завершать аргументом ].

$ [ 1 = 2
[: missing `]
$ test 1 = 2
$ echo $?
1
$ [ 1 = 1 ]
$ echo $?
0

Нужно понимать, что [ — имя команды, из-за чего нельзя писать [1=2] без пробелов: такой команды попросту нет.


help

В некоторых шеллах есть встроенная команда help, с помощью неё удобно смотреть документацию к другим встроенным выражениям, в т.ч. test:

help test

getopts

getopts помогает разбирать аргументы на флаги, используется вместе с конструкцией case:

#!/bin/sh
usage() { echo "$0 [-s <45|90>] [-p <string>]" 1>&2; }
while getopts ":s:p:" o; do
    case "${o}" in
        s)
            s=${OPTARG}
            [ $s -eq 45 -o $s -eq 90 ] || usage
            ;;
        p)
            p=${OPTARG}
            ;;
        *)
            usage
            ;;
    esac
done
shift $((OPTIND-1))
if [ -z "${s}" ] || [ -z "${p}" ]; then usage fi

Списки команд

Логическое И и логическое ИЛИ

Оператор
Описание
p1 && p2Если команда слева (p1) завершилась кодом возврата 0, то исполняем команду справа (p2) и возвращаем её код, иначе возвращаем код возврата команды слева (p1)
p1 || p2Если команда слева (p1) закончилась кодом возврата отличным от 0, то исполняем команду справа (p2) и возвращаем её код, иначе возвращаем 0.

Примеры уже упоминаемые ранее:

python -c  'exit(0)' && echo Success || echo Failure
## вывод
Success

python -c  'exit(1)' && echo Success || echo Failure
## вывод
Failure

Точка с запятой

Точка с запятой ; используется для разделения нескольких команд, которые должны выполняться последовательно, независимо от успеха или неудачи предыдущей команды.

Например,

echo "Первая команда"; echo "Вторая команда"

должно выводить:

## вывод
Первая команда
Вторая команда

subshell

subshell - это отдельный дочерний процесс shell, который создается из родительского shell.

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

Это позволяет изолированно выполнять команды и скрипты.

Можно, вызвать с помощью круглых скобок (), см. ниже. Иногда создаётся и неявно, например, в конвейерах.


Примеры:

1. Изменение текущей директории

В этом примере мы меняем директорию в subshell, и это не влияет на текущую директорию родительской оболочки.

(cd /tmp; ls)
echo "Текущая директория: $(pwd)"

Здесь команды внутри скобок (cd /tmp; ls) выполняются в subshell, а pwd показывает текущую директорию родительской оболочки.


Примеры:

2. Использование переменных

В этом примере переменная, определенная в subshell, не доступна в родительской оболочке.

(export MY_VAR="Hello"; echo $MY_VAR)
echo $MY_VAR

MY_VAR будет выведена в subshell, но второй echo $MY_VAR в родительской оболочке ничего не выведет, так как MY_VAR не определена в родительской оболочке.


Примеры:

3. Использование в скриптах

Подоболочки полезны в скриптах для изоляции выполнения определенных частей скрипта.

#!/bin/bash
echo "Начало скрипта"
( 
 echo "В subshell"
 # Выполнение команд в subshell
)
echo "Конец скрипта"

В этом скрипте команды внутри круглых скобок выполняются в subshell.

Использование subshell позволяет организовать более чистое и управляемое выполнение команд, ограничивая область видимости изменений и предотвращая побочные эффекты на родительскую оболочку.

Это особенно полезно в сложных скриптах и при выполнении операций, требующих временного изменения окружения или текущего рабочего каталога.


Круглые скобки

Круглые скобки () используются для группировки команд в subshell.

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

Например

(cd /some/directory; echo "Я в $(pwd)")

изменяет директорию только в subshell и выводит текущую директорию в нём же.


Фигурные скобки

Группировка команд с помощью фигурных скобок {} похожа на круглые скобки, но команды выполняются прямо в текущем shell, а не в subshell.

{ echo "Первая команда"; echo "Вторая команда"; }

выполняет обе команды echo в текущем shell.