Функции и аргументы

Аргументы командной строки служат для сценария переменными с числовыми именами: $1 первый аргумент командной строки, $2 второй и т.д. Аргумент $0 содержит имя, по которому был вызван сценарий, например ./bin/example.sh, т.е. это не фиксированное значение.

Переменная $# содержит количество переданных аргументов командной строки, а переменная $* все эти аргументы. Ни одна из этих переменных не учитывает аргумент $0.

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

#!/bin/bash
function show_usage {
echo "Использование: $0 source_dir dest_dir"
exit 1
}
Основная программа начинается здесь
if [ $# -ne 2 ]; then
show_usage
else # Существуют два аргумента
if [ -d $1 ]; then
source_dir=$l
else
echo 'Недопустимый каталог-источник'
show_usage
fi
if [ -d $2 ]; then
dest_dir=$2
else
echo 'Недопустимый каталог-приемник'
show_usage
fi
fi
printf "Каталог-источник: ${source_dir}\n"
printf "Каталог-приемник: ${dest_dir}\n"

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

$ mkdir ааа bbb
$ sh showusage ааа bbb
Каталог-источник: ааа
Каталог-приемник: bbb
$ sh showusage foo bar
Недопустимый каталог-источник
Использование: showusage source__dir dest_dir

Аргументы bash-функций обрабатываются практически так же, как и аргументы командной строки: $1 первый аргумент командной строки, $2 второй и т.д. Как видно из приведенного выше примера, аргумент $0 содержит имя сценария.

Для того чтобы сделать предыдущий пример более устойчивым к ошибкам, можно передавать функции show_usage в качестве аргумента код ошибки. Это позволило бы конкретизировать код возврата для каждого типа отказа. Реализация этой идеи показана в следующем фрагменте программы:

function show_usage {
echo "Использование: $0 source_dir dest_dir"
if [ $# -eq 0 ]; then
exit 99 # Выход с любым ненулевым кодом возврата
else
exit $1
fi
}

В этой версии функции добавляется анализ наличия аргументов. Внутри функции переменная $# сообщает, сколько аргументов было ей передано. Сценарий завершится с кодом возврата 99, если при его вызове не было передано никаких аргументов. Но при передаче конкретного значения, например "show_usage 5" сценарий завершится с этим кодом после вывода сообщения об использовании сценария (переменная $? содержит статус завершения последней выполненной команды, независимо от факта использования в сценарии или в командной строке).

Между функциями и командами в оболочке bash существует строгая аналогия. Можно определить полезные функции в файле ~/.bash_profile, а затем использовать их в командной строке как команды. Например, если узел стандартизировал в сети порт 7988 для протокола SSH, можно определить в файле ~/.bash_profile функцию ssh, чтобы она всегда запускалась (как команда) с ключом -р 7988.

function ssh {
/usr/bin/ssh 7988 $*
}

Подобно многим командным оболочкам, bash обладает механизмом псевдонимов (alias), который может репродуцировать этот ограниченный пример в еще более лаконичном виде, тем не менее функции остаются более универсальным и более мощным средством.