Cintu и Zsh. Вопросы истории (команд)

Алексей Федорчук

Извлечение ранее введённых команд из их «истории» — ещё один способ минимизации набора символов при работе в CLI (наряду с ранее рассмотренными hподстановками и автоматическим дополнением). И эта возможность существует по всех современных командных оболочках (кроме, разве что, кондового POSIX Shell, эмулируемого обычно командой /bin/sh). Однако и тут Zsh некогда выделился дополнительными функциями (правда, ныне реализованными и в Bash, хотя там они включаются несколько иным способом).

Для начала — несколько общих слов. Всем известно, что команды в истории оных можно последовательно просматривать, нажимая клавиши Up (назад) и Dowm (вперёд). А найдя там нужную — отправить её на исполнение нажатием клавиши Enter. При необходимости предварительно отредактировав опции и (или) аргументы. Однако это может быть занятием достаточно нудным, потому что нужно учитывать следующее.

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

А во-вторых, история команд записывается в специальный dot-файл домашнего каталога пользователя — в Cintu таковым является ~/.zhistfile. Причём в ней Zsh настроен таким образом, что вновь введённая команда попадает в файл истории сразу, а не по завершении текущего сеанса. То есть она будет последней в списке команд следующего сеанса, при открытии нового терминального окна или вкладки в существующий.

Так что при высоком лимите на количество строк в буфере сеанса и в файле истории (а в Cintu лимит этот — 2000 и 10000 строк, соответственно), перебор команд может потребовать немало времени. Конечно, файл ~/.zhistfile можно просто просмотреть, например, командой less, дабы найти нужную, в том числе и с применением фильра типа grep. Однако и это не намного легче. Даже с учётом того, что в файл истории, в соответствие с принятыми в Cintu настройками Zsh, не попадают дубликаты команд и пустые строки.

Кстати, пока не забыл: предотвратить попадание команды в историю, если это почему-либо не желательно (например, её аргумент содержит учётные данные доступа ftp-серверу), можно, введя пробел перед именем команды. Однако в буфере текущего сеанса она всё равно сохранится до конца оного, и будет доступна для «перебора» — причём именно в такой, «историко-недоступной», форме. Эта функция оказывается неоценимой на финальной стадии подготовки образов в Sytemback. Когда, казалось бы, всё уже сделано и файл истории уничтожен (дабы не «светить кухню»). Но, как обычно бывает (по крайней мере, у меня), пара мелочей, требующих выполнения команд, оказалась забытой.

Думаю, ни для кого не секрет также, что для вызова списка команд предназначена специальная команда history. Однако в данном случае следует учитывать, что это — встроенная команда оболочки, зависит от последней, а потому её возможности в Bash и в Zsh различаются. И редкий случай — не в пользу последней, поскольку в Bash её функционал обеспечивается библиотекой GNU History Library, в Zsh не задействованной.

Впрочем, потеря не велика — команда history в её Bash-модификации никогда не казалась мне очень удобной. Тем более что в Zsh есть замечательный механизм history-substring-search — поиска в истории по начальной последовательности символов.

Что это такое — проще пояснить на примере: вы вводите в командной строке один символ (для примера — s) и нажимаете клавишу Up. И тут в дальнейший «перебор» включаются только те команды из истории, которые с буковки s начинаются. Вводя дополнительные символы, можно сузить круг поиска: например, последовательность sudo позволяет просмотреть, что мы наколбасили от лица суперпользователя вообще. А если добавить ещё и apt, легко вспомнить, что было наустановлено или наудалено ранее.

Кроме того для облегчения процедуры поиска предусмотрена такая интересная возможность, как наращиваемый поиск (incremental search). Выполняется он так: после нажатия (при пустой командной строке) клавишной комбинации Control+R появляется предложение ввести алфавитный символ (или — последовательность символов произвольной длины), заведомо входящий в состав требуемой команды:

$ bck-i-search: _

Ввод такого символа выведет последнюю из команд, его содержащих. При этом введённый символ будет отмечен знаком курсора. Он не обязан входить в имя команды, но может быть составляющим её опций или аргументов (имени файла или пути к нему, например). Следующее нажатие Control+R зафиксирует курсор на предыдущем символе, в пределах этой же или более ранней по списку команды, и т.д. Однако вместо этого в строке поиска можно вводить дополнительные символы, детализирующие условия поиска команды (или — её опций и аргументов).

Процедуру поиска можно продолжать вплоть до достижения требуемого результата — то есть нахождения той команды, которая нужна именно сейчас. Нажатие клавиши Enter в любой из этих моментов запускает найденную (то есть помещенную в командную строку) команду на исполнение, с завершением поиска. Поиск обрывается также и нажатием комбинации Control+C. Перед запуском найденная команда может быть отредактирована стандартными средствами — с использованием управляющих последовательностей.

Перебор через history-substring-search и инкрементный поиск по Control+R отнюдь не исключают друг друга, а дополняют: первым способом проще искать ранее введённые директивы по имени команды, вторым — по её аргументам, например, по имени файла.

И ещё, и инкрементный поиск, и history-substring-search имеется как в Zsh, так и в Bash. И в обоих оболочках первая функция работает по умолчанию, а вторая должна быть включена в конфигурационных файлах, причём по разному. Как это делается в Zsh — расскажу под занавес, а в Bash — описано, например, здесь. Ну и справедливости ради стоит заметить, что функция history-substring-search впервые появилась в оболочке Tcsh, где она, как правило, включена по умолчанию.

Моя Cintu. Оглавление

Добавить комментарий