Возможности командной оболочки
История команд
Двумя другими клавишами со стрелками - вверх и вниз - Мефодий тоже активно пользовался, не подозревая, что задействует этим весьма мощный механизм bash - работу с историей команд. Все команды, набранные пользователем, bash запоминает и позволяет обращаться к ним впоследствии. По стрелке вверх (можно использовать и " ^P ", previous), список поданных команд "прокручивается" от последней к первой, а по стрелке вниз (" ^N ", next) - обратно. Соответствующая команда отображается в командной строке как только что набранная, ее можно отредактировать и подать оболочке (подгонять курсор к концу строки при этом необязательно).
Если необходимо добыть из истории какую-то давнюю команду, проще не гонять список истории стрелками, а выполнить поиск с помощью команды " ^R " (reverse search). При этом выводится подсказка специального вида ("reverse-i-search"), подстрока поиска (окруженная символами ` и ' ) и последняя из команд в истории, в которой эта подстрока присутствует:
[methody@localhost methody]$ ^R | (reverse-i-search)`': i | (reverse-i-search)`i': ls i n | (reverse-i-search)`in': info f | (reverse-i-search)`inf': info o | (reverse-i-search)`info': info ^R | (reverse-i-search)`info': man info ^R | (reverse-i-search)`info': info "(bash.info.bz2)Commands For History"Пример 8.3. Поиск по истории команд
Пример представляет символы, вводимые Мефодием (в левой части до " | "), и содержимое последней строки терминала. Это "кадры" работы с одной и той же строкой, показывающие, как она меняется при наборе. Набрав "info", Мефодий продолжил поиск этой подстроки, повторяя " ^R " до тех пор, пока не наткнулся на нужную ему команду, содержащую подстроку " info ". Осталось только передать ее bash с помощью Enter.
Чтобы история команд могла сохраняться между сеансами работы пользователя, bash записывает ее в файл .bash_history, находящийся в домашнем каталоге пользователя. Делается это в момент завершения оболочки: накопленная за время работы история дописывается в конец этого файла. При следующем запуске bash считывает .bash_history целиком. История хранится не вечно, количество запоминаемых команд в .bash_history ограничено (обычно сохраняется 500 команд, но это можно и перенастроить).
Сокращения
Поиск по истории - удобное средство: длинную командную строку можно не набирать целиком, а отыскать и использовать. Однако давнюю команду придется добывать с помощью нескольких " ^R " - а можно и совсем не доискаться, если она уже выбыла оттуда. Для того чтобы оперативно заменять длинные команды короткими, стоит воспользоваться сокращениями (aliases). В конфигурационных файлах командного интерпретатора пользователя обычно уже определено несколько сокращений, список которых можно посмотреть с помощью команды alias без параметров:
[methody@localhost methody]$ alias alias cd..='cd ..' alias cp='cp -i' alias l='ls -lapt' alias ll='ls -laptc' alias ls='ls --color=auto' alias md='mkdir' alias mv='mv -i' alias rd='rmdir' alias rm='rm -i'Пример 8.4. Просмотр заранее определенных сокращений
С сокращениями Мефодий уже сталкивался в примерах, приведенных в лекции 6, где команда ls отказалась работать в согласии с теорией. Выяснилось, что по команде ls вместо утилиты /bin/ls bash запускает собственную команду-сокращение, превращающееся в команду ls --color=auto. Повторно появившуюся в команде подстроку " ls " интерпретатор уже не обрабатывает, во избежание вечного цикла. Например, команда ls -al превращается в результате в ls --color=auto -al. Точно так же любая команда, начинающаяся с rm, превращается в rm -i (interactive), что Мефодия крайне раздражает, потому что ни одно удаление не обходится без вопросов в стиле " rm: удалить обычный файл `файл'?":
[methody@localhost methody]$ unalias cp rm mv [methody@localhost methody]$ alias pd=pushd [methody@localhost methody]$ alias pp=popd [methody@localhost methody]$ pd /bin /bin ~ [methody@localhost bin]$ pd /usr/share/doc /usr/share/doc /bin ~ [methody@localhost doc]$ cd /var/tmp [methody@localhost tmp]$ dirs /var/tmp /bin ~ [methody@localhost tmp]$ pp /bin ~ [methody@localhost bin]$ pp ~ [methody@localhost methody]$ pp -bash: popd: directory stack emptyПример 8.5. Использование сокращений и pushd/popd
От надоедливого " -i " Мефодий избавился с помощью команды unalias, а заодно ввел сокращения для полюбившихся ему команд bash - pushd и popd. Эти команды2Они названы по аналогии с операциями работы со стеком - pushd и popd ., подобно cd, меняют текущий каталог. Разница состоит в том, что pushd все каталоги, которые пользователь делает текущими, запоминает в особом списке (стеке). Команда popd удаляет последний элемент этого стека и делает текущим каталогом предпоследний. Обе команды вдобавок выводят содержимое стека каталогов (то же самое делает и команда dirs ). Команда cd в bash также работает со стеком каталогов: она заменяет его последний элемент новым.
Команда-сокращение (alias) - внутренняя команда shell, задаваемая пользователем. Обычно заменяет одну более длинную команду, которая часто используется при работе в командной строке. Сокращения не наследуются с окружением .
Достраивание
Сокращения позволяют быстро набирать команды, однако никак не затрагивают имен файлов, которые чаще всего и оказываются параметрами этих команд. Бывает, что набранной строки - пути к файлу и нескольких первых букв его имени - достаточно для однозначного указания на этот файл, потому что по введенному пути других файлов, чье имя начинается на эти буквы, просто нет. Чтобы не дописывать оставшиеся буквы (а имена файлов в Linux могут быть весьма длинными), Гуревич посоветовал Мефодию нажать клавишу Tab. И - о чудо! - bash сам достроил начало имени файла до целого (снова воспользуемся методом "кадров"):
[methody@localhost methody]$ ls -al /bin/base Tab | [methody@localhost methody]$ ls -al /bin/basename -rwxr-xr-x 1 root root 12520 Июн 3 18:29 /bin/basename [methody@localhost methody]$ base Tab | [methody@localhost methody]$ basename Tab | [methody@localhost methody]$ basename ex Tab | [methody@localhost methody]$ basename examples/ Tab | [methody@localhost methody]$ basename examples/-filename-with- -filename-with-Пример 8.6. Использование достраивания
Дальше - больше. Оказывается, и имя команды можно вводить не целиком: оболочка достроит набираемое слово именно до команды, раз уж это слово стоит в начале командной строки. Таким образом, команду basename examples/-filename-with- Мефодий набрал за восемь нажатий на клавиатуру (" base " и четыре Tab )! Ему не пришлось вводить начало имени файла в каталоге examples, потому что файл там был всего один.
Выполняя достраивание (completion), bash может вывести не всю строку, а только ту ее часть, относительно которой у него нет сомнений. Если дальнейшее достраивание может пойти несколькими путями, то однократное нажатие Tab приведет к тому, что bash растерянно пискнет3Все терминалы должны уметь выдавать звуковой сигнал при выводе управляющего символа " ^G ". Для этого не нужно запускать никаких дополнительных программ: "настоящие" терминалы имеют встроенный динамик, а виртуальные консоли обычно пользуются системным ("пищалкой"). В крайнем случае разрешается привлекать внимание пользователя другими способами: например, эмулятор терминала screen пишет в служебной строке "wuff-wuff" ("гав-гав")., а повторное - к выводу под командной строкой списка всех возможных вариантов. В этом случае надо подсказать командной оболочке продолжение: дописать несколько символов, определяющих, по какому пути пойдет достраивание, и снова нажать Tab.
Поиск ключевого слова "completion" по документации bash выдал так много информации, что Мефодий обратился к Гуревичу за помощью. Однако тот ответил, что не использует bash, и поэтому не в состоянии объяснять тонкости его настройки. Если в bash предусмотрено несколько типов достраивания (по именам файлов, по именам команд и т. п.), то в zsh их сколько угодно: существует способ запрограммировать любой алгоритм достраивания и задать шаблон командной строки, в которой именно этот способ будет применяться.