Встроенные команды
Мы уже отмечали, что подавляющее большинство команд разыскивается в списке поиска и выполняется языком shell в рамках порожденных процессов. Однако для некоторых команд - либо по соображениям эффективности, либо потому, что требуемую функциональность трудно достичь в рамках отдельного процесса - целесообразно сделать исключение и реализовать их как встроенные, их выполняет сам shell. Очевидным примером встроенной команды служит export - пометить переменную как глобальную, входящую в окружение процесса проще внутренними методами.
Встроенные команды подразделяются на обычные и специальные. С точки зрения приложений первые ничем (кроме, быть может, эффективности обработки) не отличаются от невстроенных утилит. В частности, они могут фигурировать в качестве программы процесса. Специальные встроенные команды этим свойством обладать не обязаны. Кроме того, у них есть еще два отличия:
- синтаксическая ошибка в специальной встроенной команде способна привести к аварийному завершению shell;
- присваивание переменным, заданное посредством специальной встроенной команды, остается в силе и после ее завершения.
Перечислим некоторые из специальных встроенных команд.
. файл
Shell читает и выполняет команды из файла, затем возобновляется чтение со стандартного ввода; при поиске файла используется значение переменной PATH. Иными словами, специальная команда . позволяет выполнить любую команду в рамках текущего процесса.
eval [аргумент ...]
Выполнить команду, заданную аргументами eval.
exec [аргумент ...]
Сменить программу процесса: в рамках текущего процесса команда, заданная аргументами exec, заменяет shell. В качестве аргументов могут указываться спецификации ввода/вывода, и, если нет никаких других аргументов, будет лишь перенаправлен ввод/вывод текущего процесса shell.
exit [код_завершения]
Завершить выполнение shell с указанным кодом. При отсутствии аргумента код завершения определяется последней выполненной командой. Чтение символа конца файла также приводит к завершению shell.
shift [n]
Формальные аргументы, начиная с (n+1)-го, переименовываются в $1 и т.д. По умолчанию n=1.
К числу обычных встроенных команд относятся:
cd [каталог]
Сделать текущим заданный каталог. Если каталог не указан, используется значение переменной окружения HOME.
pwd
Выводит имя текущего каталога.
read [переменная ...]
Со стандартного ввода читается одна строка и делится на поля; первое поле присваивается первой переменной, второе - второй и т.д., причем последовательность всех оставшихся полей присваивается последней переменной. Исходная строка имеет продолжение, если в конце ее стоит последовательность \перевод_строки. Символы, отличные от перевода строки, также могут быть экранированы с помощью \, который удаляется перед присваиванием полей. Возвращается нулевой код завершения, если только не встретился конец файла.
Некоторые пояснения. С помощью команды exec осуществляется смена программы текущего процесса. Например, если пользователь привык работать в командном интерпретаторе bash, он может перейти туда по команде
exec bash
При этом обычный shell бесследно исчезнет.
Аргументы специальной встроенной команды eval обрабатываются дважды: когда исходную строку интерпретирует shell и когда работает сама eval. Так, после выполнения строк
a=1 b=a eval c='$'$b echo $c
на стандартный вывод будет выдана единица, поскольку аргументом eval будет оператор присваивания c=$a.
Если файл data содержит строку
1 2 3 4 5
то после выполнения специальной встроенной команды read
read a b c echo $c $b $a
на стандартный вывод будет выдан следующий результат:
3 4 5 2 1
Текст "3 4 5" (остаток строки) стал значением переменной c.
Команду shift используют при последовательной обработке аргументов shell-процедур. Например, если требуется выдать аргументы, которые являются именами существующих обычных файлов, употребляют цикл вида (см. листинг 2.28):
while [ "$1" ] do [ -f $1 ] && echo $1 shift done
Листинг 2.28. Пример использования специальной встроенной команды shift. (html, txt)
Важную роль играет еще одна специальная встроенная команда - set. Она используется для изменения режима работы shell и для присваивания новых значений формальным аргументам. Сразу же отметим, что наивное присваивание
цифра=слово
shell трактует как запуск программы с именем цифра=слово, т. е. оно не позволяет изменить значение формального аргумента.
Команда set записывается в виде
set [опция ...] [аргумент ...]
Из ее опций упомянем следующие:
-a
Экспортировать в окружение все переменные, которым производится присваивание.
-C
Защищать существующие файлы от перезаписи при перенаправлении вывода посредством конструкции ">" (см. выше раздел "Перенаправление ввода/вывода").
+o
Выдать на стандартный вывод текущие опции языка shell в виде команд, которые устанавливают те же значения и которые можно подать ему на вход.
-x
Устанавливает режим трассировки после выполнения всех подстановок в командных строках, но до выполнения они будут выдаваться в стандартный протокол. Опция +x выключает трассировку. Стандарт не специфицирует, будет ли трассироваться команда set +x.
Если в команде set заданы аргументы, они станут новыми значениями $1, $2 и т.д. Типичный пример использования команды set содержится в одном из файлов ОС Linux (/etc/rc.d/rc) выполняемых при загрузке системы (см. листинг 2.29):
argv1="$1" set `/sbin/runlevel` runlevel=$2 previous=$1
Листинг 2.29. Пример использования специальной встроенной команды set. (административная утилита runlevel выдает предыдущий и текущий уровни выполнения системы). (html, txt)
Возможностью, не обязательной с точки зрения стандарта POSIX-2001 (отнесенной к расширению "Мобильность пользователей", UP), но весьма полезной на практике, является механизм синонимов для имен простых команд. Синонимы задаются с помощью обычной встроенной команды alias:
alias [имя[=синоним] ...]
Когда shell выделяет в командной строке слово, расположенное вместо имени простой команды, он проверяет, не является ли оно именем синонима, и при положительном ответе заменяет его значением, заданным командой alias и представляющим собой цепочку символов.
Например, если хочется, чтобы команда ls по умолчанию выдавала информацию о файлах, имена которых начинаются с точки, можно воспользоваться спецификацией для определения синонима:
alias ls="ls -a"
Если подставленный синоним оканчивается пробелом, то анализируется следующее слово командной строки; если и оно оказывается именем синонима, подстановки продолжаются. Например, если синоним для ls задать в виде строки с завершающим пробелом
alias ls="ls -a "
и дополнительно ввести еще одно определение синонима
alias l="-Rl"
то команда, использующая синоним с завершающим пробелом,
ls l
будет раскрыта в строку
ls -a -Rl
и выдаст в длинном формате информацию о всех файлах текущего каталога и его подкаталогов.
Команда alias без аргументов выдает список имеющихся синонимов.