Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Изучение Linux.doc
Скачиваний:
5
Добавлен:
01.07.2025
Размер:
2.5 Mб
Скачать

5.5Псевдонимы и переменные

Вернемся на минуту к команде ls. У Вас может возникнуть вполне резонный вопрос: а если я всегда хочу видеть ее вывод в цвете, да еще с символическим различением типов файлов, да еще в "длинном" формате; ну и без вывода скрытых файлов мне никак не прожить. И что же - мне каждый раз вводить кучу опций, чтобы получить столь ,элементарный эффект?

Отнюдь! Потому что этот вопрос задавали себе многие поколения пользователей. И ответили на него просто - введением понятия псевдонима команды (alias).

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

Устанавливаются псевдонимы очень просто - одноименной командой alias, в качестве аргументов которой выступают имя псевдонима и его значение, соединенные оператором присваивания (именуемым в просторечии знаком равенства). А именно, если мы хотим ныне, и присно, и во веки веков видеть вывод команды ls в цвете и символьным различением типов файлов, нам достаточно дать команду вроде следующей:

# alias ls='ls -F --color=auto'

Где следует обратить внимание на два момента:

  • на то, что имя псевдонима совпадает с именем команды (что отнюдь не препятствует создания псевдонима типа ll='ls -l' специально для вывода файловых списков в длинном формате)

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

Таким образом мы можем наделать себе псевдонимов на все случаи жизни. В разумных пределах конечно - иначе вместо упрощения жизни мы создадим себе необходимость запоминания множество невнятных сочетаний символов. Однако на наиболее важных псевдонимах я остановлюсь.

Вспомним команды типа cp и mv, которыми мы, в частности, можем скопировать или переместить какие-то файлы из каталога в каталог. А что произойдет, если чисто случайно в целевом каталоге уже имеются файлы, одноименные копируемым/перемещаемым? Произойдет штука, могущая иметь весьма неприятные последствия: файлы в целевом каталоге будут заменены новыми, теми, что копируются туда или перемещаются. То есть исходное содержание этих файлов будет утрачено - и безвозвратно, восстановить его невозможно будет никакими силами.

Разумеется, иногда так и нужно, например, при резервном копировании старые версии файлов и должны быть заменены их более свежими вариантами. Однако такое приемлемо далеко не всегда. И потому в большинстве команд, связанных с необратимыми изменениями файловой системы, предусматривается специальная опция - -i (или --interactive). Если задать эту опцию с командой cp или mv, то при совпадении имен исходного и целевого файлов будет запрошено подтверждение на выполнение соответствующего действия:

# cp file1 file2

10:13 pts/0 cp: overwrite file2'?

И пользователь может решить, нужно ли ему затирать существующий файл, ответив yes (обычно достаточно y), или это нежелательно, и должно ответить no (а также просто n - или не отвечать ничего, это равноценно в данном случае отрицательному ответу).

Так вот, дабы не держать в голове необходимость опции -i (ведь, как я уже говорил, пропуск ее в неподходящий момент может привести к весьма печальным результатам, в подавляющем большинстве систем для команд cp и mv (а также для команды rm, служащей для удаления файлов - в POSIX-системах эта операция также практически необратима) определяются одноименные им псевдонимы такого вида:

# alias cp='cp -i'

# alias mv='mv -i'

# alias rm='rm -i'

Все это, конечно, очень благородно, заметит внимательный читатель. Но что, если мне заведомо известно, что сотни, а то и тысячи файлов целевого каталога должны быть именно переписаны новыми своими версиями (как тут не вспомнить про случай с резервным копированием)? Что же, сидеть и, как дурак, жать на клавишу Y?

Не обязательно. Потому что все команды рассматриваемого класса имеют еще опцию -f (в "длинной" своей форме, --force, она также практически универсальна для большинства команд). Которая, отменяя действие опции -i, предписывает принудительно переписать все файлы целевого каталога их обновленными тезками. И никто не мешает нам на этот случай создать еще один псевдоним для команды cp, например:

# alias cpf='cp -f'

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

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

# unalias alias_name

То есть дав директиву

# unalias cp

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

# alias

без опций и аргументов выведет полный их список:

la='ls -A' less='less -M' li='ls -ial' ll='ls -l' ls='ls -F --color=auto'

и так далее.

Когда я сказал о пользовании псевдонимами ныне, и присно, и вовек, - то был не совсем точен. Ныне, то есть в текущем сеансе пользователя - да, они работают. Однако после рестарта системы (или просто после выхода из данной оболочки) они исчезнут без следа. Чтобы заданные псевдонимы увековечить, их нужно прописать в конфигурационном файле пользовательского шелла. Но этим мы займемся впоследствии. А пока обратимся к переменным.

Переменные

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

Что такое переменная? Ответ просто - некоторое имя, которому присвоено некоторое значение.

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

Таким встроенных переменных довольно много. И одна из первых по значению – переменная PATH. Это - список каталогов, в которых оболочка, в ответ на ввод пользователя в командной строке, ищет исполнимые файлы - то есть просто команды. Вы, наверное, обратили внимание, что во всех приведенных выше примерах имена команд указывались без всяких путей к ним (в отличие от файлов-аргументов, путь к которым - обязателен). Так вот, успех ее поисков и определяется списком значений переменной PATH, которые могут быть просмотрены командой echo

# echo $PATH

Обратим внимание на то, что в качества аргумента команды выступает не просто имя переменной, а оно же, но предваренное символом доллара. Который, в данном случае, никакого отношения к приглашению командной строки не имеет, а предписывает команде echo подменить имя переменной ее значением (значениями). В данном случае вывод команды будет примерно таким:

/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin

Тем временем вернемся к переменной PATH Значение ее - полный абсолютный путь к домашнему каталогу пользователя. То есть, чтобы перейти в него, пользователю по имени alv вместо

# cd /home/alv

достаточно набрать

# cd $HOME

и он в своих владениях. Может показаться, что экономия - грошовая, но минуту терпения - и выгоду от использования переменных вы увидите.

Кроме переменных, предопределенных в шелле, пользователю предоставляется почти полная свобода в определении переменных собственных. И вот тут-то и наступает ему обещанное облегчение при наборе аргументов команд.

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

/home/alv/data/all.my.works/geology/plate-tectonics

Весьма удручающе для набора, даже если исправно работать табулятором для автодополнения, не так ли? Прекрасно, упрощаем себе жизнь определением переменной:

# PLATE=/home/alv/data/all.my.works/geology/plate-tectonics

Дело в шляпе, Теперь, если нам нужно просмотреть состав этого каталога, достаточно будет команды

# ls $PLATE

А вызвать из него любой файл для редактирования можно так:

# vim $PLATE/filename

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

# NAME=Value

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

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

Чтобы избежать такой неприятной ситуации, было придумано понятие переменной окружения, или переменной среды - environment variable. Это - те переменные, которые наследуются от родительского шелла всеми дочерними программами. И чтобы сделать их таковыми, переменные следует экспортировать. Как? Командой export, которая может быть применена двояким образом. Можно сначала определить переменную:

# NAME=Value

а затем применить к ней команду export:

# export NAME

А можно сделать это в один прием:

# export NAME=Value

Второй способ применяется, если нужно определить и экспортировать одну переменную. Если же за раз определяется несколько переменных:

# NAME1=Value1 $ NAME2=Value2 ... $ NAMEN=ValueN

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

# export NAME1 NAME2 ... NAMEN

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

Существуют и иные способы присвоения значений переменным. Одно неизменно - значение переменной это строка. Например, значение переменной можно присвоить используя строку вывода некоторой команды.

variab3=`cat /var/run/inetd.pid`

Здесь переменной variab3 присваивается значение вывода, полученной от команды, заключенной в одинарные кавычки. В данном случае значение переменной variab3 будет PID демона inetd. Значение переменной можно получить и интерактивно, т.е. с клавиатуры.

echo -n "Введите свое имя" read username

При запуске командный интерпретатор выведет строку "Введите свое имя" и будет ждать ввода с клавиатуры. Строка, введенная пользователем, и будет значением переменной username. Вообще говоря, read может присвоить значения сразу нескольким переменным.

echo -n "Введите свое имя и фамилию" read username userfamname

Если пользователь введет свое имя и фамилию через пробелы, то переменным username и userfamname присвоятся соответственно строки с именем и фамилией пользователя. Если же введенных значений больше чем определено read, они игнорируются. В случае же пустых присвоений, значение переменной также пусто.

При использовании любой переменной Shell подставляет ее значение. Существуют также и более сложные конструкции получения непосредственно значения переменной.

$variable - Значение variable, или ничего если переменная не определена.

${variable} - Аналогично, с отделением имени variable от последующих символов.

${variable:-string} - Значение variable, если переменная определена. В противном случае string. Значение variable остается неизменным.

${variable:=sring} - Значение variable, если переменная определена. В противном случае string, при этом variable присваивается значение string.

${variable:?string} - Так называемая "обязательная переменная". Если variable не определена, выводится строка string и интерпретатор прекращает работу. Если же и строка string пуста, в таком случае выводится variable: parameter not set

${variable:+string} - Строка string, если переменная variable определена. В противном случае ничего.