Оглавление

Работа с историей команд bash

Настройка размера истории

Количество хранимых команд определяется двумя переменными: HISTSIZE и HISTFILESIZE. Первая определяет количество команд, хранимых в памяти, вторая — в файле. Их уместно устанавливать в ~/.bachrc. Такие значения, мне представляются оптимальными:

HISTSIZE=5000
HISTFILESIZE=10000

Настройка способа сохранения

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

shopt -s histappend

которую тоже уместно написать в ~/.bachrc.

Простой просмотр истории

Вся история:

history

Пять последних команд:

history 5

В сочетании с grep:

history | grep cd

Но это всё только присказка.

Выполнение команд из истории по номеру

Восклицательный знак выполняет команду с данным номером. Пример:

~$ ls -ld /bin
lrwxrwxrwx 1 root root 7 май 31  2013 /bin -> usr/bin
~$ history 3
 4220  cd
 4221  ls -ld /bin
 4222  history 3
~$ !4221
ls -ld /bin
lrwxrwxrwx 1 root root 7 май 31  2013 /bin -> usr/bin
~$ echo !4221
echo ls -ld /bin
ls -ld /bin

Как видно из последней команды, подстановка с восклицательным знаком может быть частью другой команды. Она может быть использована в пайпе или в другом контексте. Примеры:

$ sudo !4221
$ !4221 >/dev/null

Номер может быть относительным, с конца: !-2. Специальное сокращение !! — последняя команда.

Передвижение по истории

Все знают о том, что по истории можно двигаться клавишами-стрелками. Но иногда бывают ситуации, когда эти клавиши недоступны, работают не правильно, или просто отсутствуют (у меня такое было, когда я подключался каким-то ssh-клиентом с iPad). На этот случай полезно знать, что промотка работает по Ctrl-p и Ctrl-n.

Поиск по истории

Режим поиск включается по Ctrl-r. Для поиска следующего совпадения надо повторно нажать Ctrl-r. Для передвижения по совпадениям в другую строну есть сочетание клавиш Ctrl-s.

Проблема в том, что Ctrl-s в большинстве терминалов приводит к засыпанию. Чтобы выйти из сна, нажмите Ctrl-q. Чтобы отключить засыпание, есть команда:

stty -ixon

Поиск по истории по началу команды

Bash (а вернее readline) поддерживает очень удобный стиль поиска — по первым символам команды. К сожалению, по умолчанию, этот механизм недоступен. Чтобы его включить, надо написать в ~/.inputrc что-то такое:

# Shift-[Up][Down]
"\e[1;2A" history-search-backward
"\e[1;2B" history-search-forward

Теперь вы можете набрать начало команды и нажать Shift-<стрелка вверх>. И для вас будет найдена последняя команда из истории с таким же началом. Стрелки с клавишей Shift теперь позволяют двигаться по совпадениям.

Естественно, можно настроить любые другие клавиши.

Подстановки и изменения команд

Вы уже видели три простейшие подстановки:

После восклицательного знака можно указывать подстроку-начало команды.

!ls — последняя команда ls (со всеми аргументами).

Можно указывать подстроку для поиска:

!?encoder? последняя команда с подстрокой encoder.

Операции с отдельными словами

Все слова (параметры разделённые пробелами) доступны через модификатор : (двоеточие). Пример:

$ cd /home
$ echo !!:1
echo /home
/home

Здесь !! — ссылка на последнюю команду, а :1 ссылка на её первый аргумент. Поэтому, в нашем примере echo !!:1 преобразуется в echo /home.

Для этого случая: когда мы оперируем именно с последней командой, можно опускать один восклицательный знак и двоеточие:

$ echo !1

Есть и привычные сокращения: первый аргумент — ^, последний — $, все — *. Имеются ввиду именно параметры команды. Без учёта самой команды.

Манипуляции с путями и именами файлов

Следующий уровень модификаторов позволяет минимально управлять именами файлов.

Модификатор :t даёт доступ к имени файла. Эта удобно скажем в таком сценарии работы:

Вы обращаетесь к некому файлу, указывая полный путь:

cat /etc/hosts

Потом переходите в директорию с этим файлом

cd /etc

Выполняете ещё какие-то команды, а потом решаете отредактировать файл. Тогда вы можете написать так:

vi !cat:$:t

То есть, вы находите в историю последнюю команду cat (!cat), берёте её последний аргумент :$, а от него оставляете только имя файла :t.

Модификатор :h работает противоположно, он отрезает имя файла, оставляя весь остальной путь. Это полезно, например, когда вы хотите перейти в директорию с последним просмотренным файлом:

vi /etc/hosts
cd $vi:$:h

Последняя команда перейдёт в директорию /etc.

Последний модификатор из этой серии — :r. Он отрезает расширение. Его можно указывать несколько раз, есть вы хотите отрезать несколько расширений (.tar.gz).