Операционная система GNU/Linux — Лабораторная работа № 4
Курсивное начертание
Программирование в командном интерпретаторе
Методические указания:
В ходе выполнения лабораторной работы студент знакомится с теоретическими сведениями, пробует примеры, находит ответы на контрольные вопросы. В отчёт заносится протокол работы: какие команды опробованы, зачем они нужны, а также ответы на контрольные вопросы.
Общие сведения
Синтаксис, возможности и сам набор команд в системах UNIX определяется интерпретатором команд (shell, оболочка). Существует несколько разновидностей интерпретаторов, входящих в любую поставку UNIX: Bourne shell (sh), Korn shell (ksh), C shell (csh), Bourne again shell (bash), Touch shell (tcsh) и др. Каждый из них имеет свои функциональные возможности. В процессе работы можно переключиться с одного интерпретатора на другой, запустив соответствующую программу. Оболочка по умолчанию задаётся пользователю при создании его учётной записи в системе. Командный интерпретатор, используемый по умолчанию в GNU/Linux — bash.
bash — совместимый с sh командный интерпретатор, выполняющий команды, поступающие на стандартный ввод или из файла. Файлы, содержащие команды для интерпретатора, называют сценариями (script). bash реализует многие полезные возможности интерпретаторов ksh и csh. bash соответствует спецификации POSIX 1003.2 для командных интерпретаторов и системных утилит.
Все встроенные команды bash описаны в разделе «SHELL BUILTIN COMMANDS» в конце справочного руководства man bash. Быстрый доступ к справочной информации по той или иной встроенной команде bash осуществляется при помощи встроенной команды help.
При входе пользователя в систему bash выполняет сначала общесистемный сценарий /etc/profile, а затем один из пользовательских сценариев настройки[1] ~/.bash_profile, ~/.bash_login или ~/.profile (какой найдёт первым). Экземпляр оболочки, запускаемый при входе пользователя в систему, называется начальной оболочкой (login shell). Когда начальная оболочка завершает работу (по [Ctrl]+[d] закончился стандартный ввод или пользователь выполнил встроенные команды exit или logout[2]), сеанс работы пользователя закрывается, при этом выполняется сценарий ~/.bash_logout. Если запускаются другие экземпляры оболочки, не являющиеся начальными (но интерактивными), выполняется сценарий ~/.bashrc. Когда оболочка запускается в неинтерактивном режиме (например, для выполнения пользовательского сценария), выполняется конфигурационный сценарий, имя которого хранится в переменной окружения BASH_ENV (если только эта переменная непустая).
В конфигурационном сценарии устанавливаются значения переменных окружения. Большинство из них принимает определённые значения при старте системы, однако, пользователь может по своему желанию переопределять эти значения. Кроме того, пользователь может переопределять команды, присваивая каким-либо вариантам команд или их комбинациям псевдонимы (aliases), тем самым создавая свою систему команд по вкусу.
Задание 1: Выясните, какие из упомянутых сценариев присутствуют в вашей системе.
Переменные окружения
Переменной окружения (параметром) называется некоторый объект, имеющий значение. Совокупность параметров образует среду окружения (environment), переменные которой доступны каждой запущенной из оболочки команде. Особенности функционирования многих команд зависят от тех или иных переменных окружения. Переменная имеет имя, значение и опционально атрибуты. Имена переменных окружения чувствительны к регистру букв! Переменная становится доступной после присвоения ей значения. Обратите внимание, при присваивании значения переменной вокруг знака присваивания не должно быть пробельных символов! Атрибуты можно назначить переменной при объявлении её во встроенной команде declare (или typeset, export, readonly, local). Значение переменной может быть получено при помощи специального преобразования: $NAME (NAME — имя переменной):
$ echo $SHELL - $BASH_VERSION /bin/bash - 2.05b.0(1)-release $ A=123 $ echo $A 123 $ A=A+1 $ echo $A A+1 $ declare -i A=123 $ echo $A 123 $ A=A+1 $ echo $A 124
Задание 2: Опробуйте приведённый пример и объясните, почему последовательность команд «A=A+1» и «echo $A» даёт разный результат в этих случаях.
Просмотреть значения всех определённых переменных можно с помощью встроенных команд set или declare без параметров. Удалить переменную из среды окружения можно при помощи встроенной команды unset.
Ещё один способ задать значение какой-либо переменной — использовать встроенную команду read. В этом случае значение переменной считывается со стандартного ввода. Если команде read не указать никакого параметра, считанное значение присваивается переменной REPLY.
Специальный тип переменных окружения — позиционные параметры (аргументы командной строки). Позиционные параметры обозначаются цифрами (1, 2, 3 и т. д.) Значения позиционным параметрам присваиваются при запуске оболочки либо при помощи команды set. Непосредственным присваиванием изменить значение позиционных параметров нельзя. При получении значения позиционного параметра, обозначенного двумя и более цифрами, его обозначение следует заключать в фигурные скобки.
Некоторые параметры имеют специальное назначение в оболочке. На них можно только ссылаться, но непосредственно их значение изменить нельзя. Такие специальные параметры обозначаются различными знаками, перечисленными в таблице (полный список — в man bash, раздел «PARAMETERS», подраздел «Special Parameters»):
# | Соответствует количеству позиционных параметров |
* @ |
Оба параметра соответствуют всему множеству аргументов командной строки, то есть при подстановке значения этих специальных параметров подставляются все заданные аргументы командной строки. Различие наблюдается при использовании этих параметров в кавычках (см. пример). В этом случае значение параметра * подставляется как одно слово (то есть как "$1 $2 $3 …"), а при использовании параметра @ позиционные параметры подставляются как отдельные слова (то есть как "$1" "$2" "$3" …) |
? | Содержит статус выхода последней выполненной команды. Нулевой статус выхода соответствует успешному завершению программы |
$ | Содержит PID выполняющегося командного интерпретатора |
0 | Содержит имя выполняющейся оболочки или сценария |
$ set a b c d e f g h i j k l m n $ echo $10 ${10} a0 j $ set "$@" $ echo $# 14 $ set "$*" $ echo $# 1
Задание 3: Почему команда «echo $#» в этом примере вывела разные результаты? Что выведет «echo $1», «echo $2»? Почему?
Интерпретатор bash версии 2.0 и новее поддерживает параметры-массивы, старше версии 4.0 — ассоциативные массивы. Массивы в bash являются одномерными. Для массивов нет явного ограничения на размер, также не является обязательным требование непрерывности нумерации элементов. Обычный массив нет необходимости специально объявлять (хотя это можно сделать при помощи declare -a) — массив создаётся при задании значения любому его элементу. Элементы массивов нумеруются с нуля.
Ассоциативный массив надо явно объявлять при помощи declare -A.
Элементу массива можно присвоить значение при помощи команды:
Чтобы задать значения нескольким элементам массива, можно использовать следующий синтаксис:
где вместо значения-i может быть использовано выражение:
A=(a b c) | эквивалентно | A[0]=a; A[1]=b; A[2]=c |
B=([3]=z [5]=q [13]=w) | эквивалентно | B[3]=z; B[5]=q; B[13]=w |
declare -A C=([garbalo]=ruskei [muuroi]=keldaine [musťoi]=mustu) | эквивалентно | declare -A C C[garbalo]=ruskei; C[muuroi]=keldaine; C[musťoi]=mustu |
Для получения значения элемента массива используется следующая запись: ${имя[индекс]}. Если в качестве индекса использован символ * или @, вместо этого выражения подставляются все элементы массива. Различие в использовании * или @ наблюдается только тогда, когда это выражение заключено в кавычки. В таком случае вместо "${имя[*]}" подставляется "${имя[0]} ${имя[1]} …", а вместо "${имя[@]}" — "${имя[0]}" "${имя[1]}" … Вместо выражения ${#имя[индекс]} подставляется длина элемента с указанным индексом. Если в качестве индекса указан символ * или @, подставляется количество элементов в массиве.
$ echo $BASH_VERSINFO 2 $ for i in "${BASH_VERSINFO[@]}"; do echo = $i =; done = 2 = = 05b = = 0 = = 1 = = release = = i586-mandrake-linux-gnu = $ for i in "${BASH_VERSINFO[*]}"; do echo = $i =; done = 2 05b 0 1 release i586-mandrake-linux-gnu =
Обратите внимание, что тело первого цикла выполняется 6 раз, а тело второго цикла — только 1 раз. Использование имени массива без указания индекса подразумевает обращение к элементу с индексом 0.
Для удаления массива или его отдельных элементов можно использовать встроенную команду unset.
Задание 4: По справочному руководству man bash, раздел «PARAMETERS», подраздел «Shell variables» выясните назначение следующих переменных: BASH, BASH_VERSINFO, BASH_VERSION, HOSTNAME, HOSTTYPE, MACHTYPE, OSTYPE, PWD, RANDOM, REPLY, SHLVL, UID, HOME, LANG, PATH, PS1, PS2, PS3. Запишите значение перечисленных переменных для того экземпляра оболочки, в котором вы работаете.
Задание 5: Измените вид строки приглашения для вашей среды так, чтобы она содержала время. Как сделать, чтобы эта настройка сохранилась при перезапуске оболочки?
Псевдонимы
Псевдоним — это строка символов, подставляемая оболочкой вместо первого слова командной строки. Псевдонимы определяются при помощи встроенной команды alias и удаляются при помощи unalias. Чтобы просмотреть список определённых псевдонимов, запустите alias без параметров. Синтаксис команды:
Например:
$ alias DIR='ls -la' $ DIR итого 65188 drwxr-xr-x 3 pupkin pupkin 4096 Сен 6 21:36 ./ drwx------ 7 pupkin pupkin 4096 Сен 8 12:59 ../ drwxr-xr-x 2 pupkin pupkin 4096 Май 9 14:16 bmk/ -rw-r--r-- 1 pupkin pupkin 1033427 Фев 22 2003 etc.tgz lrwxrwxrwx 1 pupkin pupkin 13 Сен 6 21:36 home -> /home/pupkin/ -rw-r--r-- 1 pupkin pupkin 65626430 Фев 22 2003 home.tgz
Установки переменных окружения и псевдонимы определены только для текущего экземпляра оболочки. Порождённые процессы и дочерние оболочки получают в свою среду окружения параметры, для которых задано свойство экспортирования (при помощи ключа -x в команде declare или команды export). Однако дочерние процессы не могут изменить среду окружения родительской оболочки, и все изменения переменных и определения псевдонимов теряются при выходе из дочернего процесса.
Задание 6: В DOS/Windows команды COPY, REN и DEL выполняют, соответственно, копирование, переименование и удаление файлов. Определите такие псевдонимы, назначив им аналогичные команды UNIX.
Задание 7: В разделе «COMMAND EXECUTION» справочного руководства по bash выясните приоритет, в котором выполняется поиск соответствия имени команды. Выясните назначение встроенных команд builtin, command, enable и type.
Шаблоны (имён файлов)
В различных конструкциях bash могут использоваться шаблоны. В шаблоне любой символ, кроме перечисленных в следующей таблице специальных символов, сопоставляется с самим собой. Если требуется сопоставить себе один из специальных символов, следует применять экранирование.
* | Сопоставляется с любой подстрокой, в том числе с пустой |
? | Сопоставляется с любым ровно одним символом |
[…] | Сопоставляется с одним из символов, перечисленных в квадратных скобках. Можно использовать минус (-) для определения диапазона символов. Если первым символом внутри скобок является ! или ^, то шаблон сопоставляется с любым из символов, НЕ перечисленных в скобках. Внутри скобок могут использоваться идентификаторы классов символов: [:alnum:] [:alpha:] [:ascii:] [:blank:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:word:] [:xdigit:] |
Использование такого шаблона в свободном параметре командной строки подразумевает сопоставление этого шаблона с именами файлов в соответствующем каталоге и называется преобразованием пути (pathname expansion). Имена файлов подставляются в алфавитном порядке.
Примеры:
$ echo ~/.bash* /home/pupkin/.bash_history /home/pupkin/.bash_logout /home/pupkin/.bash_profile /home/pupkin/.bashrc $ ls /etc/[knqwy]* /etc/krb5.conf /etc/nsswitch.conf /etc/warnquota.conf /etc/ytalkrc /etc/ksysguarddrc /etc/qt.fontguess /etc/wgetrc $ echo *.abc *.abc
Если файлов, соответствующих шаблону не найдено, то поведение зависит от опций оболочки (nullglob и failglob): может быть выведена пустая строка, выдано сообщение об ошибке или выдан неизменённый текст самого шаблона (именно последний вариант является поведением по умолчанию).
Задание 8. Какой шаблон следует использовать в команде du -hs, чтобы получить размеры всех скрытых каталогов в текущем каталоге. Не забудьте исключить из вывода каталоги «.» и «..».
Простая команда, конвейер, список, составные команды
Простая команда (simple command) может содержать следующие элементы (в порядке следования, разделённые пробелами):
- определения переменных окружения
- имя команды (или путь к исполняемому файлу)
- аргументы команды (позиционные параметры)
- операции перенаправления
Конец простой команды определяется одним из ограничителей:
Примеры:
ls -l >test.ls MANWIDTH=40 man bash GREP_COLOR=\001 GREP_OPTIONS="--color=always" grep bash \ </etc/passwd
Переменные, значения которым заданы в составе простой команды, попадают только в её среду окружения и никак не влияют на среду окружения оболочки.
Синтаксис конвейера (pipeline):
При этом стандартный вывод ПростойКоманды1 подаётся на стандартный ввод ПростойКоманды2 и т. д.
Пример:
cat /etc/passwd | grep bash | tr : " "
Список (list) — это последовательность одного или нескольких конвейеров (или простых команд), разделённых знаками:
Эта последовательность может быть завершена точкой с запятой (;), амперсандом (&) или ограничителем «конец строки». Ограничители «точка с запятой» и «конец строки» предназначены для простого разделения команд в списке, такие команды выполняются последовательно. Там, где стоит точка с запятой, может быть конец строки и наоборот. Если команда завершается амперсандом, она выполняется в фоновом режиме. Оболочка не ожидает её завершения и приступает к выполнению следующей команды в списке.
Управляющие операции списка «&&» и «||» используются следующим образом:
команда1 || команда2
В первом случае команда2 выполняется, только если команда1 выполнилась успешно (вернула нулевой статус выхода). Во втором случае команда2 выполняется, только если команда1 выполнилась неуспешно (вернула ненулевой статус выхода). В примерах ниже использованы команды true и false, которые ничего не делают, а всегда возвращают определённый статус выхода: true возвращает статус 0 (успешный), а false возвращает статус 1 (неуспешный).
$ true && uname Linux $ false && uname $ true || uname $ false || uname Linux
Составные команды (compound commands):
В цикле выполняются команды из списка LIST. В каждой итерации цикла параметру NAME присваивается очередное слово из списка WORDS (параметры, разделённые пробелами). Цикл завершается, когда все слова из списка WORDS исчерпаны.
$ for A in 1 2 3 ; do echo $A ; done 1 2 3
Перед выполнением цикла по правилам арифметических выражений вычисляется EXPR1. Перед выполнением очередной итерации цикла проверяется значение арифметического выражения EXPR2. Если его значение отлично от нуля, выполняется список LIST и вычисляется выражение EXPR3. Когда значение выражения EXPR2 становится равным 0, цикл завершается.
$ for ((A=100; A>=96; A--)); do echo $A; done 100 99 98 97 96
Задание 9: Запишите цикл for, суммирующий числа от 1 до 10.
Выполняется список, стоящий после if. Если список выполняется успешно (статус выхода 0), то выполняется список, стоящий после then. В противном случае выполняется список, стоящий после elif или после else.
Задание 10: Запишите условный список «cmd1 && cmd2» при помощи составной команды if. Запишите условный список «cmd1 || cmd2» при помощи составной команды if. Для инвертирования статуса выхода команды можно использовать операцию «!».
На стандартный вывод ошибок выдаётся пронумерованный список слов WORDS. Со стандартного ввода в переменную REPLY читается строка, а затем выполняется список LIST. При этом если введённая строка содержит номер одного из указанных слов, то переменной NAME присваивается это слово, в противном случае NAME остаётся пустой. Эта последовательность действий выполняется до тех пор, пока не будет выполнена встроенная команда break или не закончится стандартный ввод.
$ select R in a b c; do echo Reply: [$REPLY] R:[$R] > if [ "$R" == a ]; then break; fi > done 1) a 2) b 3) c # ? q Reply: [q] R:[] # ? 2 Reply: [2] R:[b] # ? 1 Reply: [1] R:[a]
Слово WORD последовательно сравнивается со всеми шаблонами PATTERN. При нахождении соответствия, выполняется список LIST, стоящий после подходящего шаблона. Дальнейшие сопоставления не производятся.
$ case $OSTYPE in > linux* | freebsd*) uname;; > *) echo Unknown system;; > esac Linux
until LIST1 ; do LIST2 ; done
Список LIST2 выполняется до тех пор, пока статус выхода LIST1 не станет отличен от нуля (для while) или не станет равным нулю (для until).
Внутри циклических команд могут быть использованы встроенные команды break и continue. Команда break немедленно завершает цикл, а команда continue вызывает немедленный переход к очередной итерации.
Преобразования
При обработке командной строки bash, встретив неэкранированные специальные символы, выполняет определённые преобразования.
При преобразовании скобок (brace expansion) выражение вида «a{d, c, b}e» заменяется на «ade ace abe». Это преобразование может быть вложенным. Сортировка по алфавиту не выполняется — сохраняется порядок слева направо.
Примеры:
$ echo test{1,2,3,4} test1 test2 test3 test4 $ ls /{bin,sbin}/*sh /bin/bash /bin/rbash /bin/tcsh /bin/csh /bin/sh
Если слово начинается с тильды (~), выполняется преобразование тильды (tilde expansion): вместо одиночной тильды подставляется путь к домашнему каталогу текущего пользователя; вместо выражения ~username — путь к домашнему каталогу указанного пользователя; вместо ~+ подставляется значение переменной PWD (текущий каталог); вместо ~- подставляется значение переменной OLDPWD (каталог, который был текущим до выполнения последней команды cd).
Преобразование параметров (parameter expansion) обозначается знаком доллара ($). В зависимости от сопутствующих символов со значением указанной переменной окружения выполняются различные преобразования.
$NAME или ${NAME} |
Вместо выражения подставляется значение параметра NAME. Фигурные скобки обязательны, только если параметр является позиционным с номером больше 9 или после имени параметра следует символ, который может быть интерпретирован как часть имени, но ею не является |
${!NAME} | Косвенная подстановка. Подставляется значение параметра, имя которого хранится в NAME |
${!PREFIX*} или ${!PREFIX@} |
Подставляются все имена переменных, начинающиеся с указанного префикса |
${NAME:-WORD} | Если параметр NAME не установлен либо пуст, вместо выражения подставляется WORD, в противном случае подставляется значение параметра |
${NAME:OFS} ${NAME:OFS:LEN} |
Подстановка подстроки. Вместо выражения подставляется не более LEN символов из значения параметра NAME, начиная с символа со смещением OFS (смещения от 0). Если смещение отрицательно, символы отсчитываются от конца строки. Вместо NAME может быть * или @, тогда подставляются позиционные параметры, начиная с параметра с индексом OFS в количестве не более LEN штук. То же самое касается массивов с индексом * или @ |
${#NAME} | Подставляется размер значения параметра NAME в символах. В качестве NAME может быть использован массив с индексом * или @, тогда возвращается количество элементов в массиве |
${NAME#PATTERN} ${NAME##PATTERN} |
Вместо выражения подставляется значение параметра NAME, при этом из начала значения параметра вырезается минимальная (для #) или максимальная (для ##) подстрока, соответствующая шаблону PATTERN |
${NAME%PATTERN} ${NAME%%PATTERN} |
Вместо выражения подставляется значение параметра NAME, при этом из конца значения параметра вырезается минимальная (для %) или максимальная (для %%) подстрока, соответствующая шаблону PATTERN |
${NAME/PTRN/STR} ${NAME//PTRN/STR} |
Вместо выражения подставляется значение параметра NAME, в котором первая подстрока (для /) или все подстроки (для //) максимальной длины, соответствующие шаблону PTRN, заменены на STR. Если STR отсутствует, подстроки удаляются |
Следующие примеры позволяют наблюдать разницу между различными вариантами преобразований:
$ ZZZ=1qwerty2qwerty3qwerty $ echo ${ZZZ:14} 3qwerty $ echo ${ZZZ:7:7} 2qwerty $ echo ${ZZZ:(-3):2} rt $ echo ${ZZZ#1q*rt} y2qwerty3qwerty $ echo ${ZZZ##1q*rt} y $ echo ${ZZZ%qw*ty} 1qwerty2qwerty3 $ echo ${ZZZ%%qw*ty} 1 $ echo ${ZZZ/q/\'} 1'werty2qwerty3qwerty $ echo ${ZZZ//q/\'} 1'werty2'werty3'werty
Задание 11: В примере выше придумайте преобразование, которое удалит из значения параметра ZZZ все символы.
Задание 12: При помощи преобразования ${!PREFIX*} и цикла for выведите значения всех переменных, имена которых начинаются на BASH.
Подстановка команды (command substitution) подразумевает, что вместо выражения будет подставлен текст, выданный на стандартный вывод командой, содержащейся в выражении. Есть две равнозначные формы синтаксиса подстановки команды:
`команда` | $(команда) |
Обратите внимание, в первом случае используются не прямые апострофы (одинарные кавычки), а обратные (на клавиатуре располагаются, как правило, рядом с [Tab]).
Специальный случай подстановки команды: вместо $(cat файл) можно использовать $(<файл), то есть вместо выражения будет подставлено содержимое указанного файла.
Задание 13: Что помещается в переменную A при присваивании A=`ls`? Что помещается в переменную B при присваивании B=`<~/.bash_history`?
Арифметическая подстановка (arithmetic expansion) предназначена для вычисления арифметических выражений и подстановки результата: $((выражение)). Например:
$ echo 5+6=$((5+6)) 5+6=11
Арифметические выражения
Арифметические выражения используются в арифметических подстановках, а также во встроенной команде let. Вместо команды let "выражение" можно использовать следующий синтаксис:
В любом случае такая команда вычисляет выражение по правилам для арифметических выражений и возвращает успешный статус выхода (0), если результат выражения отличен от нуля, и неуспешный статус выхода (1), если результат арифметического выражения — нуль. При вычислении арифметических выражений bash оперирует только целыми числами с разрядностью, соответствующей архитектуре машины (32 или 64 бита). Воспринимаются те же арифметические операции, что и в языке Си, с таким же порядком приоритета:
В качестве операндов могут стоять переменные окружения без использования преобразования параметров. Константы, начинающиеся с 0, считаются восьмеричными. Константы, начинающиеся с 0x или 0X, считаются шестнадцатеричными. Константы, начинающиеся с num# (где num=2…64), считаются заданными в системе исчисления по основанию num. В противном случае константа считается десятичной.
Примеры:
$ echo $((5+6)) 11 $ ((10>20)) $ echo $? 1 $ ((10<20)) $ echo $? 0
Задание 14: Прокомментируйте следующий пример:
$ A=2#111 $ let A++ $ printf %o\\n $A 10
Условные выражения
Условные выражения указываются в составном операторе [[…]] и во встроенной команде test (или в её синониме […]). Условные выражения используются для проверки атрибутов файлов, а также сравнения строк и чисел. Если условное выражение истинно, команда [[…]] или test даёт успешный статус выхода (0). Ложному условному выражению соответствует неуспешный статус выхода (1).
Полностью с возможностями условных выражений можно ознакомиться в man bash, раздел «CONDITIONAL EXPRESSIONS». Некоторые возможные операции перечислены в следующей таблице.
-e файл | (exists) Истинно, если файл (директория) существует |
-f файл | (file) Истинно, если файл существует и является обычным файлом |
-d файл | (directory) Истинно, если файл существует и является директорией |
-r файл | (readable) Истинно, если файл (директория) существует и доступен для чтения |
-w файл | (writable) Истинно, если файл (директория) существует и доступен для записи |
-x файл | (eXecutable) Истинно, если файл (директория) существует и является исполняемым (для пользователя доступен режим доступа «x») |
-s файл | (size) Истинно, если файл существует и имеет ненулевой размер |
-z строка | (zero) Истинно, если длина строки равна нулю (строка пустая) |
-n строка | (non-empty) Истинно, если длина строки не равна нулю (строка непустая) |
строка1 == строка2 строка1 != строка2 |
Сравнение строк на равенство или неравенство |
арг1 OP арг2 | Сравнение численных аргументов. OP может быть: -eq (равно), -ne (не равно), -lt (меньше), -le (меньше или равно), -gt (больше), -ge (больше или равно) |
Обратите внимание, квадратные скобки для bash не является метасимволами (то есть разделителями слов), поэтому в условных выражениях квадратные скобки отбиваются пробелами от остальных аргументов.
Примеры:
$ [[ 10 -gt 20 ]] $ echo $? 1 $ [[ 10 -lt 20 ]] $ echo $? 0 $ if test $RANDOM -gt 15000 > then echo big > else echo small ; fi ok $ if test $RANDOM -gt 15000 > then echo big > else echo small ; fi try again $ test -r /etc/passwd && echo file is readable file is readable $ [ -r /etc/shadow ] && echo file is readable $ [ -r /etc/shadow ] || echo file is NOT readable file is NOT readable
Задание 15: Объясните, что делают следующие команды:
[ -f /tmp/123 ] && rm -f /tmp/123 [ -d /tmp/345 ] || mkdir /tmp/345
Сценарии командного интерпретатора
Командный интерпретатор может обрабатывать команды не только со стандартного ввода (из командной строки), но и из текстового файла — сценария. Принято помещать в первую строку сценария так называемый «шебанг» (sharp+bang, то есть «решётка», или «октоторп» плюс «восклицательный знак») — путь к интерпретатору в виде:
#!путь опции
Это не особенность bash, а общесистемный механизм UNIX-подобных операционных систем. Если исполняемый файл не является бинарным, то он должен начинаться с «шебанга», чтобы система знала, какой интерпретаттор для него надо запустить (Perl, Python, PHP, …).
В сценариях bash строки, начинающиеся с октоторпа (#), считаются комментариями и игнорируются (как и пустые строки).
Запуск сценария на выполнение может осуществляться несколькими способами. Если файл сценария является исполняемым, то сценарий можно запустить, просто указав его имя в качестве команды (в нём обязательно должен быть «шебанг»). Обратите внимание, что система ищет команды только в каталогах, указанных в переменной окружения PATH, в противном случае надо писать путь к исполняемому файлу. Для запуска сценария можно также использовать встроенные команды source или . (точка). В таком случае имя сценария передаётся как аргумент командной строки (а «шебанг» необязателен).
Пример сценария:
#!/bin/bash num=${1:-0} a='#' for ((i=0; i<num; i++)) do echo $a a="#$a" done
Если сценарий назвать myscript.sh, то в работе он будет выглядеть следующим образом:
$ source myscript.sh 3 # ## ###
Задание 16: Напишите сценарий, выполняющий... (по вариантам)
Примечания: