В оглаление
См. также: Coreutils - основные команды.
Редактирование ввода
Редактирование командной строки
Некоторое время поработав в Linux, понабирав команды в
командной строке, приходишь к выводу, что в общении с оболочкой не
помешают кое-какие удобства. Одно из таких удобств — возможность
редактировать вводимую строку с помощью клавиши Backspace
(удаление последнего символа), Ctrl+W (удаление
слова) и Ctrl+U (удаление всей строки) —
предоставляет сам терминал Linux. Эти команды работают для любого
построчного ввода в терминале. Если по каким-то причинам в строчку на
экране влез мусор, можно нажать Ctrl+R (redraw) —
система
выведет
в
новой
строке содержимое входного буфера.
Командная оболочка поддерживает некоторые базовые операции по
редактированию командной строки, которых можно ожидать для любого
текстового ввода. Речь идёт о клавишах Стрелка влево
и Стрелка вправо, с помощью которых можно
перемещать курсор по командной строке, и клавише Del,
удаляющей
символ
под курсором, а не позади него. Помимо этого
перемещаться в командной строке можно не только по одному сиволу вперёд
и назад, но и по словам: команды ESCF
/ESCB
или Alt+F
/Alt+B
соответственно (от forward и backward),
работают
также
клавиши
Home и End,
или, что то же самое, Ctrl+A и Ctrl+E.
История команд
Bash располагает весьма мощным механизмом — возможностью
работать с историей команд. Все команды, набранные
пользователем, bash
запоминает и позволяет обращаться к
ним впоследствии. Для работы с историей команд используются клавиши со
стрелками — вверх и вниз. По стрелке вверх (можно использовать и Ctrl+P,
previous), список поданных команд
«прокручивается» от последней к первой, а по стрелке вниз (Ctrl+N,
next) — обратно. Соответствующая команда
отображается в командной строке как только что набранная, её можно
отредактировать и подать оболочке (подгонять курсор к концу строки при
этом не обязательно).
Если необходимо добыть из истории какую-то давнюю команду,
проще не гонять список истории стрелками, а поискать в ней с
помощью команды Ctrl+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"
Пример 1. Поиск по истории
команд
Пример представляет символы, вводимые пользователем (в
левой части до “|
”), и содержимое последней строки
терминала. Это «кадры» работы с одной и той же строкой, показывающие,
как она меняется при наборе. Набрав «info», пользователь продолжил
поиск этой подстроки, повторяя Ctrl+R до тех
пор, пока не наткнулся на нужную ему команду, содержащую подстроку “info
”.
Осталось
только
передать
её
bash
с помощью Enter.
Чтобы история команд могла сохраняться между
сеансами работы пользователя, bash
записывает её в файл .bash_history
,
находящийся
в
домашнем
каталоге
пользователя. Делается это в момент завершения
оболочки: накопленная за время работы история дописывается в конец
этого файла. При следующем запуске bash
считывает .bash_history
целиком. История хранится не вечно, количество запоминаемых команд в .bash_history
ограничено (обычно 500 командами, но это можно и перенастроить).
Сокращения
Поиск по истории — удобное средство: длинную командную
строку можно не набирать целиком, а выискать и использовать. Однако давнюю
команду придётся добывать с помощью нескольких Ctrl+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'
Пример 2. Просмотр заранее
определённых сокращений
Выяснилось, что по команде ls
вместо утилиты
/bin/ls
bash
запускает собственную
команду-сокращение, превращающееся в команду ls --color=auto
.
Повторно появившуюся в команде подстроку “ls
”
интерпретатор
уже
не
обрабатывает,
во избежание вечного цикла.
Например, команда ls -al
превращается в результате в ls
--color=auto
-al
. Точно так же любая команда, начинающаяся с rm
,
превращается
в
rm -i
(interactive), в
результате чего ни одно удаление не обходится без вопросов в стиле «rm:
удалить обычный файл `файл'
?». Избавиться от ненужного
сокращения можно с помощью команды unalias
.
Достраивание
Сокращения позволяют быстро набирать команды, однако
никак не затрагивают имён файлов, которые чаще всего и
оказываются параметрами этих команд. Бывает, что набранной
строки — пути к файлу и нескольких первых букв его имени —
достаточно для однозначного указания на этот файл, потому что
по введённому пути болшьше файлов, чьё имя начинается на эти буквы,
просто нет. Чтобы не дописывать оставшиеся буквы в bash
можно нажать клавишу 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/sample-file
sample-file
Пример 3. Использование
достраивания
Дальше — больше. Оказывается, и имя команды можно
вводить не целиком: оболочка догадается достроить набираемое слово
именно до команды, раз уж это слово стоит в начале командной строки.
Таким образом, команда basename examples/sample-file
была
набрана за восемь нажатий клавиш («base» и четыре Tab)!
Не
потребовалось
вводить
начало
имени файла в каталоге examples
,
потому
что файл там был всего один.
Выполняя достраивание (completion), bash
может вывести не всю строку, а только ту её часть, относительно которой
у него нет сомнений. Если дальнейшее достраиване может пойти несколькими
путями, то однократное нажатие Tab приведёт к
тому, что bash
растерянно пискнет, а
повторное — к выводу под командной строкой списка всех
возможных вариантов. В этом случае надо подсказать командной оболочке
продолжение: дописать несколько символов, определяющих, по какому пути
пойдёт достраивание, и снова нажать Tab.
Дополнения в bash
находятся ещё не на самой
вершине удобства и экономии нажатий на клавиши. Если в bash
несколько типов достраивания (по именам файлов, по
именам команд и т. п.), то в zsh
их сколько угодно:
существует
способ
запрограммировать
любой
алгоритм достраивания и
задать шаблон командной строки, в которой именно этот способ будет
применяться.
Генерация имён файлов
Достраивание очень удобно, когда цель пользователя —
задать один конкретный файл в командной строке. Если же нужно
работать сразу с несколькими файлами — например для
перемещения их в другой каталог с помощью mv
,
достраивание не помогает. Необходим способ задать одно «общее» имя,
которое будет описывать сразу группу файлов, с которыми будет работать
команда. В подавляющем большинстве случаев это можно сделать при помощи
шаблона.
Шаблоны
Символы в шаблоне разделяются на обычные и специальные.
Обычные
символы
означают
сами
себя, а специальные обрабатываются особым
образом:
- Шаблону, стостоящему только из обычных символов,
соответствует единственная строка, состоящая из тех же
символов в том же порядке. Например, шаблону “
abc
”
соответствует строка abc
, но не aBc
или ABC
,
потому
что
большие
и
маленькие буквы различаются.
- Шаблону, состоящему из единственного спецсимвола “
*
”,
соответствует
любая строка любой длины (в том числе и пустая).
- Шаблону, состоящему из единственного спецсимвола “
?
”,
соответствует
любая строка длиной в один символ,
например, a
, +
или @
, но не ab
или 8888
.
- Шаблону, состоящему из любых символов, заключённых в
квадратные скобки “
[
” и “]
” соответствует
строка длиной в один символ, причём этот символ должен встречаться
среди заключённых в скобки. Например, шаблону “[bar]
”
соответствуют только строки a
, b
и r
,
но
не
c
, B
, bar
или ab
.
Символы
внутри
скобок
можно
не перечислять полностью, а задавать диапазон,
в
начале которого стоит символ с наименьшим ASCII-кодом, затем следует “-
”,
а
затем —
символ
с
наибольшим ASCII-кодом. Например, шаблону “[0-9a-fA-F]
”
соответствует
одна
шестнадцатеричная цифра (скажем, 5
, e
или C
). Если после “[
” в шаблоне следует “!
”,
то
ему
соответствует
строка
из одного символа не
перечисленного между скобками.
- Шаблону, состоящему из нескольких частей,
соответствует строка, которую можно разбить на столько же подстрок
(возможно, пустых), причём первая подстрока будет отвечать первой части
шаблона, вторая — второй части и т. д. Например, шаблону “
a*b?c
”
будут
соответствовать
строки
ab@c
(“*
”
соответвтует пустая подстрока), a+b=c
и aaabbc
,
но
не
соответствовать
abc
(“?
” соответвтует
подстрока c
, а для “c
” соответствия не
находится), @ab@c
(нет соответствия для “a
”)
или aaabbbc
(из трёх b
превое соответствует
“b
”, второе — “?
”, а вот третье
приходится на “c
”).
Использование шаблонов
Шаблоны используются в нескольких конструкциях shell. Главное
место их применения — командная строка. Если оболочка видит в
командной строке шаблон, она немедленно заменяет его на список файлов,
имена
которых
ему
соответствуют.
Команда, которая затем вызывается,
получает в качестве параметров список файлов уже безо всяких шаблонов,
как если бы этот список пользователь ввёл вручную. Эта способность
командного интерпретатора называется генерацией имён файлов.
[methody@localhost methody]$ ls .bash*
.bash_history .bash_logout .bash_profile .bashrc
[methody@localhost methody]$ /bin/e*
/bin/ed /bin/egrep /bin/ex
[methody@localhost methody]$ ls *a*
sample-file
[methody@localhost methody]$ ls -dF *[ao]*
Documents/ examples/ loop to.sort*
Пример 4. Использование
шаблона в командной строке
При использовании шаблонов новичок может натолкнуться на
несколько «подводных камней». В приведённом примере только первая
команда срабатывает не вопреки ожиданиям: шаблон “.bash*
”
был
превращён
командной
оболочкой
в список файлов, начинающихся на .bash
,
этот
список
получила в качестве параметров командной строки утилита ls
,
после
чего
честно
его
вывела. “/bin/e*
” — это на
самом деле опасная команда, с которой в данном случае просто повезло:
этот шаблон превратился в список файлов из каталога /bin
,
начинающихся на “e
”, и первым файлом в списке
оказалась безобидная утилита /bin/echo
. Поскольку в
командной строке ничего, кроме шаблона, не было, именно строка /bin/echo
была воспринята оболочкой в качестве команды, которой —
в качестве параметров — были переданы остальные
элементы списка — /bin/ed
, /bin/egrep
и /bin/ex
.
Что же касается ls *a*
, то кажется, что эта
команда должна была выдать список файлов в текущем каталоге, имя
которых содержит “a
”. Вместо этого на экран
вывелось имя файла из подкаталога examples
... Впрочем,
никакой чёрной магии тут нет. Во-первых, имена файлов вида “.bash*
”
хотя
и
содержат
“a
”, но начинаются на точку, и, стало
быть, считаются скрытыми. Скрытые файлы попадают в
результат генерации имён только если точка в начале указана явно
(как в первой команде примера). Поэтому по шаблону “*a*
” в
домашнем каталоге bash
нашёл только подкаталог с именем examples
,
его-то
он
и
передал
в качестве параметра утилите ls
. Что
вывелось на экран в результате образовавшейся команды ls examples
?
Конечно,
содержимое
каталога.
Шаблон
в последней команде из примера, “*[ao]*
”,
был
превращён в список файлов, чьи имена содержат “a
” или “o
” —
Documents examples loop to.sort
, а ключ “-d
”
потребовал
у
ls
показывать информацию о каталогах, а не
об их содержимом. В соответствии с ключом “-F
”, ls
расставил “/
” после каталогов и “*
” после
исполняемых файлов.
Ещё одно отличие генерации имён от стандартной обработки
шаблона — в том, что символ “/
”, разделяющий элементы
пути, никогда не ставится в соответствие “*
” или
диапазону. Происходит это не потому, что искажён алгоритм, а потому,
что при генерации имён шаблон применяется именно к элементу пути,
внутри которого уже нет “/
”. Например, получить список
файлов, которые находятся в каталогах /usr/bin
и /usr/sbin
и содержат подстроку “ppp
” в имени, можно с помощью
шаблона “/usr/*bin/*ppp*
”. Однако одного
шаблона, который бы включал в этот список ещё и каталоги /bin
и /sbin
— то есть подкаталоги другого
уровня вложенности — по стандартным правилам сделать нельзя.
Если перед любым специальным символом стоит “\
”,
этот символ лишается специального значения, экранируется:
пара
“\символ
” заменяется командным
интерпретатором на “символ
” и передаётся в
командную строку безо всякой дальнейшей обработки:
[methody@localhost methody]$ echo *o*
Documents loop to.sort
[methody@localhost methody]$ echo \*o\*
*o*
[methody@localhost methody]$ echo "*o*"
*o*
[methody@localhost methody]$ echo *y*
*y*
[methody@localhost methody]$ ls *y*
ls: *y*: No such file or directory
Пример 5. Экранирование
специальных символов и обработка «пустых» шаблонов
Обратите внимание, что шаблон, которому не соответствует ни
одного имени файла, bash
раскрывать не стал, как
если бы все “*
” в нём были экранированы. В самом деле,
какое из двух зол меньшее: изменять интерпретацию
спецсимволов в зависимости от содержимого каталога, или сохранять
логику интерпретации с риском превратить команду с параметрами в
команду без параметров? Если бы, допустим, шаблон, которому
не нашлось соответствия, попросту удалялся, то команда ls *y*
превратилась бы в ls
и неожиданно выдала бы содержимое
всего каталога. Авторы bash
(как и Стивен Борн, автор
самой первой командной оболочки — sh
) выбрали более
непоследовательный, но и более безопасный первый способ.
Лишить специальные символы их специального значения можно и
другим способом. Разделители (пробелы, символы табуляции и символы
перевода строки) перестают восприниматься таковыми, если часть
командной строки, их содержащую, окружить двойными или одинарными
кавычками. В кавычках престаёт «работать» и генерация имён (как это
видно из примера), и интерпретация других специальных символов. Двойные
кавычки, однако, допускают выполнение подстановок
переменной окружения и результата работы команды.