Что такое ZSH и почему его следует попробовать в качестве альтернативы Bash?
ZSH, также называемая оболочкой Z, является расширенной версией Bourne Shell (sh) с множеством новых функций и поддержкой плагинов и тем. Поскольку она основана на той же оболочке, что и Bash, ZSH имеет многие из тех же функций, и переключиться на него очень просто.
Чем ZSH лучше Bash?
У ZSH слишком много функций, чтобы перечислять их здесь, часть из них — лишь незначительные улучшения в Bash, но вот некоторые из основных:
- Автоматический cd: просто введите имя каталога
- Рекурсивное расширение пути: например, «/u/lo/b» заменяется на «/usr/local/bin»
- Исправление орфографии и приблизительное завершение: если вы допустили незначительную ошибку при вводе имени каталога, ZSH исправит её за вас.
- Поддержка плагинов и тем: ZSH включает множество различных фреймворков плагинов.
Поддержка плагинов и тем, вероятно, самая крутая функция ZSH, и на этом мы сосредоточимся здесь.
Установка ZSH
macOS
zsh --version
перед установкой из Homebrew. Если он новее 4.3.9, возможно, всё будет в порядке. Желательно новее или равно 5.0.
brew install zsh
Чтобы установить zsh в качестве оболочки по умолчанию, выполните следующие действия, предполагая, что по умолчанию установлена Homebrew.
Последние версии Mac OS:
chsh -s /usr/local/bin/zsh
Mac OS High Sierra и более ранние версии:
chsh -s /bin/zsh
Предполагая, что у вас установлен Homebrew. В противном случае большинство версий macOS по умолчанию поставляют zsh, но обычно это более старая версия. В качестве альтернативы вы также можете использовать MacPorts
sudo port install zsh zsh-completions
Ubuntu, Debian и производные (Windows 10 WSL | Собственное ядро Linux с Windows 10 build 1903, Kali Linux, Linux Mint, elementary OS, Zorin OS, Raspbian, MX Linux, Deepin)
sudo apt install zsh
OpenSUSE
zypper install zsh
Arch Linux or Manjaro
pacman -S zsh
Void Linux
xbps-install zsh
Fedora
dnf install zsh
OpenBSD
Для установки этого пакета:
pkg_add zsh
Для установки этого пакета:
pkg install zsh
Для установки порта:
cd /usr/ports/shells/zsh/ && make install clean
Чтобы уменьшить использование памяти, необязательно включите параметры zsh-mem с помощью
make config
перед запуском «make install«.
Centos/RHEL
sudo yum update && sudo yum -y install zsh
Cygwin
Установите пакет zsh с помощью установщика. К сожалению, Cygwin не имеет стандартного интерфейса командной строки. Однако вы можете настроить apt-cyg и установить zsh следующим образом:
apt-cyg install zsh
Самый простой способ изменить оболочку по умолчанию — установить переменную пользовательской среды SHELL. Найдите «Изменить переменные среды для вашей учётной записи» («Edit Environment variables for your account»), чтобы открыть окно переменных среды, создайте новую переменную с именем «SHELL» и присвойте ей значение «/usr/bin/zsh/».
В качестве альтернативы: откройте Cygwin (в BASH), затем введите:
sudo nano ~/.bashrc
После открытия файла .bashrc добавьте эту строку в самый верх:
exec zsh
Закройте и сохраните файл. Закройте и снова откройте Cygwin. Он будет выполнять команду каждый раз, когда вы загружаете терминал и запускаете оболочку zsh.
Solus
eopkg it zsh
Funtoo/Gentoo
emerge app-shells/zsh
Alpine Linux
apk add zsh
MSYS2
pacman -S zsh
Termux (Android)
Termux — эмулятор терминала для Android, но имеет современные функции, такие как в Debian и Ubuntu (Termux имеет оболочку Bash и программы, подобные GNU Busybox). Для менеджера пакетов Termux использует менеджер пакетов Debian/Ubuntu, APT. Чтобы установить пакет, выполните эту команду:
pkg install zsh
Команда выглядит как менеджер пакетов FreeBSD (pkg). Или вы можете запустить эту команду:
apt update && apt upgrade apt install zsh
Чтобы установить zsh в качестве оболочки по умолчанию, выполните эту команду:
chsh -s /data/data/com.termux/files/usr/bin/zsh
chsh -s $(which zsh)
Установка Oh-My-Zsh
Oh-My-Zsh — это самый популярный фреймворк для ZSH, который также имеет множество встроенных плагинов и тем. Есть также пара других фреймворков для плагинов, в том числе Antigen, который является полным менеджером пакетов для ZSH, но Oh-My-Zsh имеет множество встроенных плагинов и хорошо выполняет свою работу.
У Oh-My-Zsh есть простой сценарий установки, который вы можете запустить:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
Оттуда вы можете включать и отключать плагины, добавляя их в свой файл .zshrc, расположенный в вашем каталоге ~.
Вы можете получить полный список плагинов в репозитории Oh-My-Zsh.
Темы
Существует множество тем, но некоторые считают, что powerlevel10k одна из лучших. Она добавляет выровненное по правому краю информационное окно, интеграцию с git и историей команд, невероятную настройку и оборачивает всё это в приятный интерфейс на основе плагина powerline для vim.
Вы захотите использовать iTerm на macOS или на любом терминале с 24-битным цветом, чтобы получить максимальную отдачу от powerlevel10k (или любой другой темы ZSH).
Чтобы настроить powerlevel10k (если вы установили Oh-My-Zsh), просто клонируйте репозиторий в папку пользовательских тем .oh-my-zsh:
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
Затем вам нужно включить его в .zshrc:
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>! ~/.zshrc
После загрузите .zshrc и вы должны увидеть внесённые изменения.
source ~/.zshrc
При желании вы можете настроить приглашение по умолчанию, указав POWERLEVEL9K_LEFT_PROMPT_ELEMENTS в вашем .zshrc. Вот мой с минимальным приглашением командной строки:
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(vcs dir rbenv) POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(root_indicator background_jobs status load)
Вы можете найти полную документацию для powerlevel10k в репо.
Связанные статьи:
- Как узнать, какая оболочка используется в Linux (87%)
- Как вывести значения всех переменных и переменных окружения в Linux (87%)
- Что такое TTY в Linux? (и как использовать команду tty) (63.1%)
- Скрипты, выполняемые при запуске Bash (57.6%)
- Как проверить использование памяти на Linux (50%)
- Как использовать кавычки в регулярных выражениях grep (RANDOM — 7.6%)
Переход с bash на zsh
Чтобы перейти с bash на zsh необходимо знать базовые отличия между ними — без этого будет сложно провести первоначальную настройку zsh в ~/.zshrc .
Я не нашёл краткого описания этих отличий когда переходил сам, и мне пришлось потратить немало времени на вычитывание документации zsh. Надеюсь, эта статья упростит вам переход на zsh.
Зачем переходить
Для начала — а стоит ли вообще тратить своё время и внимание на переход? Учить ещё один диалект sh, менее распространённый чем POSIX sh или bash, заново заниматься настройкой рабочего окружения…
На мой взгляд, если вы проводите много времени в консоли, вам нравятся Vim или Emacs и вы уже потратили немало времени на их настройку «под себя» — однозначно стоит! Zsh по духу очень на них похожа: это очень сложная и гибкая программа, чьи возможности полностью мало кто знает, но потратив некоторое время на настройку можно получить очень удобную лично вам рабочую среду.
Что касается изучения нового диалекта sh… пользы от этого, скорее всего, действительно мало, но описанного в этой статье минимума должно быть достаточно чтобы настраивать zsh, а писать новые скрипты на диалекте zsh вам никто и не предлагает. В общем и целом это ничем не отличается от необходимости минимально знать VimL или Emacs Lisp исключительно для настройки Vim/Emacs.
В инете куча статей и презентаций описывающих конкретные фичи zsh, значительно упростившие чью-то жизнь. Я не буду их перечислять, потому что фичи всем нужны разные, и в zsh найдутся варианты на любой вкус. Вместо этого я опишу ключевые особенности zsh, которые позволили реализовать эти фичи:
- Zsh не использует readline для ввода команд пользователем. Вместо этого используется собственный редактор ZLE (Zsh Line Editor). Это позволило реализовать множество фич: удобное редактирование многострочных команд, подсветку синтаксиса прямо в процессе ввода команды, особую обработку «paste» из clipboard чтобы не выполнить случайно вставленный текст, гибкое управление горячими клавишами, undo (в т.ч. отменяющее результат автодополнения и разворачивания glob-ов)… плюс интегрировать функционал редактора с zsh, что позволяет управлять его поведением через обычные функции zsh (например, подсветка синтаксиса так и реализована).
- Невероятно сложный и гибкий механизм автодополнения команд. Он сильно зависит от контекста, поэтому при нажатии в разных местах командной строки будут дополняться разные вещи: имена команд, их параметры, файлы, имена пользователей и серверов, номера процессов, названия переменных, индексы массивов и ключи хешей, элементы синтаксиса zsh, названия цветов и шрифтов, сетевых интерфейсов, системных пакетов… короче, вообще всего что можно автодополнять. И его можно детально контролировать, вплоть до изменения логики автодополнения для конкретного контекста у конкретной команды.
- Громадное количество (177 в zsh-5.2) опций, изменяющих поведение zsh. С их помощью можно, например, изменять поддерживаемый синтаксис и включать (в т.ч. частично) режимы совместимости с sh/bash/ksh/csh. Они позволяют настолько значительно влиять на работу, что в zsh пришлось сделать отдельный «режим совместимости с zsh», который многие функции обычно включают первой командой, потому что только это даёт им гарантию, что код этой функции будет понят zsh именно так, как ожидал его автор.
- Предпочтение максимально сжатого, краткого синтаксиса — чтобы вам нужно было набирать как можно меньше текста для выполнения типичных, пусть даже довольно сложных, задач. В коде, где важна читабельность через месяц — это однозначно минус. Но в командной строке — однозначно плюс.
- Модульная организация настроек через фреймворки (вроде oh-my-zsh и prezto), плагины, темы, etc. На самом деле здесь нет ничего специфичного для zsh, ровно то же самое можно сделать и для bash, но… почему-то для zsh всё это уже есть, а для bash — нет (а если и есть, то про это мало кто знает). А это даёт возможность относительно быстро собрать свой вариант настроек zsh из готовых «кубиков» (как пример, посмотрите видео менеджера плагинов zsh Аntigen), точно так же, как обвешивается плагинами Vim.
Отличия и совместимость
Ещё раз уточню, что я буду описывать именно отличия от bash, а не полный набор возможностей zsh. Большая часть привычного вам функционала работает в zsh точно так же, как и в bash. Но при этом часто есть специфичные для zsh способы делать примерно то же самое. Это связано с тем, что в zsh уделяется очень много внимания совместимости с другими шеллами, поэтому в zsh плюс к своим фичам перетащили очень многое из других шеллов — и в результате получили несколько альтернативных способов делать одно и то же.
Термины
- Параметр: обычная переменная — скаляр (строка, целое, дробное), массив, ассоциативный массив (хеш). А переменными называют в основном переменные окружения, т.е. экспортированные скалярные параметры.
- Аргумент: параметр (в традиционном смысле) вызываемой команды или функции (аргументы функции доступны через параметры $@ , $1 , …).
- Шаблон: глоб. Как правило шаблоны подразумевают совпадение с реально существующими файлами, но в некоторых случаях они применяются к строке или значению параметра. Поддержка полноценных регулярок тоже есть, но в основном везде в качестве шаблонов для совпадения или поиска/замены используются глобы.
- Флаги: задаются в круглых скобках перед тем, на что они должны влиять. Для параметров задаются между открывающей фигурной скобкой и именем параметра: $ . Для шаблонов могут быть в начале или середине: *CaseImportant(#i)CaseIgnored*.txt .
- Квалификаторы: задаются в круглых скобках после шаблона, уточняя его свойствами не связанными с именем файла: *(/^F) .
- Модификаторы: задаются каждый после двоеточия, применяются по очереди изменяя текущее значение. Для параметров задаются после имени параметра: $PWD:h:t , $ . Для шаблонов задаются перед закрывающей круглой скобкой квалификаторов: *(:e) .
Текущие настройки
Многие встроенные команды выводят текущее состояние при запуске без аргументов (плюс нередко у них есть аргумент, который оформляет вывод в стиле команд zsh, что довольно удобно).
# текущие опции setopt # полный список всех опций setopt KSH_OPTION_PRINT; setopt # список обрабатываемых кнопок в текущем режиме bindkey # список обрабатываемых кнопок во всех режимах, в формате команд zsh for m in $(bindkey -l); bindkey -M $m -L # текущие стили (контекстно-зависимые настройки) zstyle zstyle -L # текущие алиасы (обычные плюс глобальные), в формате команд zsh alias -L # текущие алиасы для суффиксов, в формате команд zsh alias -s -L # текущие параметры (переменные) typeset # текущие параметры (переменные), в формате команд zsh typeset -p
Это далеко не полный список, но для большинства задач в процессе (анализа) настройки zsh его должно хватить.
Ещё может быть полезным запуск zsh -f — это запускает zsh в состоянии по умолчанию (без выполнения любых стартовых скриптов кроме /etc/zshenv , которого в большинстве систем и так нет).
setopt и emulate
- В именах опций регистр и подчёркивания значения не имеют, плюс перед любой опцией можно добавить префикс «no».
- Вызов для одной и той же опции setopt с префиксом «no» и unsetopt без «no» (равно как и наоборот!) делают одно и то же.
- В выводе setopt используются маленькие буквы без подчёркиваний, в документации используются большие буквы с подчёркиваниями. Это создаёт некоторое неудобство — при поиске в документации нужно догадаться, где вставлять подчёркивания чтобы найти нужную опцию.
- Команда emulate позволяет массово установить группу опций в состояние совместимости с sh, ksh, csh или в состояние по умолчанию для zsh. Многие функции в zsh начинаются командой emulate -L zsh , что позволяет на время выполнения функции привести ключевые опции в состояние по умолчанию для zsh — без этого большинство нетривиальных функций может ломаться из-за выставленных пользователем опций (например, есть опция которая управляет тем, как индексируются массивы — от 1 или от 0).
# все эти команды делают одно и то же setopt nonumericglobsort setopt NO_numericglobsort setopt NO_NUMERIC_GLOB_SORT setopt _N_O_numERICglob_SORT_ unsetopt NUMERIC_GLOB_SORT unsetopt numericglobsort
В начале использования zsh, для более привычной работы после bash, я бы рекомендовал следующие опции:
# традиционный стиль перенаправлений fd unsetopt MULTIOS # поддержка ~… и file completion после = в аргументах setopt MAGIC_EQUAL_SUBST # не обрабатывать escape sequence в echo без -e setopt BSD_ECHO # поддержка комментариев в командной строке setopt INTERACTIVE_COMMENTS # поддержка $(cmd) в $PS1 etc. setopt PROMPT_SUBST
Ещё есть опция SH_WORD_SPLIT , и формально для привычной работы после bash её тоже надо включить, но я бы этого не рекомендовал: поведение zsh без этой опции более удобное и логичное, лучше сразу к нему привыкать. Она отвечает за то, как сработает cmd $PARAM если значение $PARAM это строка содержащая пробелы: в bash cmd получит несколько аргументов, а в zsh — один (как если бы вызвали cmd «$PARAM» ). А если $PARAM это массив, то zsh передаст cmd по одному аргументу на каждый не пустой элемент массива (даже если эти элементы содержат пробелы).
(В основном, эта статья описывает поведение zsh с опциями по умолчанию, иначе каждое второе предложение пришлось бы уточнять в стиле «но вот при таких-то опциях всё это работает иначе».)
Параметры
- Соглашение: для имён скалярных параметров (строки, целые и дробные числа) обычно используют $БОЛЬШИЕ буквы, а для массивов (обычных и ассоциативных) — $маленькие .
- Через typeset -U можно объявить массив с уникальными элементами (попытки добавления уже существующих элементов будут игнорироваться).
- Через typeset -T можно связать массив со скаляром в формате $PATH . Несколько таких связанных параметров уже созданы: $PATH и $path , $FPATH и $fpath , $MANPATH и $manpath , $CDPATH и $cdpath . Для связанных параметров не имеет значения какой из них мы изменяем — изменяются сразу оба. Поэтому в zsh с такими параметрами практически всегда работают через массивы ( $path , $fpath , …) — это значительно удобнее.
- Некоторые скалярные параметры так же связаны между собой, например $PS1 , $PROMPT и $prompt (хотя, это скорее просто синонимы для одного параметра).
Массивы
- Индексируются с 1.
- Можно использовать отрицательные индексы (от конца массива).
- Можно использовать срезы.
- При использовании как скаляра — объединяют элементы через пробел.
- Индексирование скаляра возвращает символы строки.
- Глоб возвращает массив, так что индекс можно использовать как квалификатор глоба: *([2,-2]) .
Шаблоны
- **/ — совпадает с подкаталогом любого уровня вложенности, включая отсутствие подкаталога
- — совпадает с числом в заданном диапазоне в имени файла, и начало и конец диапазона можно не указывать
- (шаблон1|шаблон2) — альтернатива (так же — группирующие скобки при использовании опции EXTENDED_GLOB )
- если включить опцию EXTENDED_GLOB , то в шаблонах можно будет дополнительно использовать # (повтор предыдущего элемента), ~ и ^ (исключение из совпадения)
# показать файлы в текущем каталоге или его подкаталогах, # которые содержат в имени число большее или равное 5 либо строку example, # и у которых расширение .txt ls -l **/*(|example)*.txt
Флаги/Квалификаторы/Модификаторы
Квалификаторы есть только у шаблонов, они позволяют задать дополнительные условия отбора файла: по типу (файл/каталог/симлинк/etc.), правам, времени (изменения/etc.), размеру… Можно сортировать и индексировать отобранные файлы. Можно включить для конкретно этого шаблона совпадение начальной * с именами начинающимися на точку. Можно включить удаление этого шаблона из аргументов командной строки если он не совпал ни с одним файлом.
# до 5-ти подкаталогов текущего каталога, # имена которых могут начинаться на точку и содержат "a", # которые изменялись последними ls -ld *a*(D/om[1,5])
Если включить опцию EXTENDED_GLOB , то в шаблонах можно будет использовать флаги: для файлов интерес представляет управление чувствительностью к регистру, а при совпадении с параметром/строкой есть и другие полезные флаги.
# эти команды идентичны ls -ld .[cC][oO][nN][fF][iI][gG]* setopt extendedglob; ls -ld .(#i)Config*
Для параметров доступно намного больше флагов: вывод всех (включая пустые) элементов массива даже в кавычках, выполнение join или split по заданной подстроке, вывод только ключей и/или значений ассоциативного массива, экранирование разными видами кавычек и обратная операция, etc.
# вывод ключей ассоциативного массива вместо значений echo $ # преобразовать $PATH в массив разделив на элементы по ":", # после чего корректно взять каждый элемент в одинарные кавычки echo $<(s<:>qq)PATH>
И для шаблонов и для параметров можно использовать модификаторы: удаление последнего элемента пути, удаление всех элементов пути кроме последнего, удалить/оставить расширение, экранирование и обратная операция, поиск и замена подстроки, etc.
# вывод имени родительского каталога (сначала отбрасываем последний # элемент пути, потом отбрасываем все элементы пути кроме последнего) echo $PWD:h:t # вывести имена (без каталога) всех симлинков в любом подкаталоге, # заменив в них подстроку "fil" на "FIL" (если такая подстрока есть) echo **/*(@:t:s/fil/FIL/)
autoload -Uz
Помимо традиционного способа подгружать код через source /path/to/file.sh или . /path/to/file.sh в zsh активно используется автозагрузка кода в момент первого вызова функции.
Для поиска файла с нужной функцией используется $FPATH — переменная аналогичная по формату $PATH , содержащая список каталогов в которых выполняется поиск файла с именем, идентичным имени загружаемой функции.
При вызове autoload никаких файлов с диска не считывается, и даже не проверяется их наличие — всё это произойдёт при первом вызове функции. Практически всегда необходимо передавать autoload аргументы -U (отменяет эффект текущих alias-ов для загружаемого файла, потому что нередко alias-ы настроенные пользователем могут нарушать работу сторонних функций) и -z (необязательное уточнение что загружаемый файл — в формате zsh, но безопаснее его всегда задавать).
fpath=(~/my-zsh-functions $fpath) autoload -Uz fn fn
При этом содержимое файла ~/my-zsh-functions/fn может быть в одном из этих трёх форматов:
# Просто набор команд, без каких-либо функций: echo "Я функция fn"
# Одна функция с именем совпадающим с именем файла: fn()
# Набор из любых команд и функций, включая fn: fn() < fn2 >fn2() < echo "Я хелпер функции fn" >echo "Выполнится перед первым запуском fn" # Но файл должен содержать явный вызов fn: fn "$@" echo "Выполнится после первого запуска fn"
zkbd
При первом запуске zsh нередко оказывается, что часть кнопок вроде F1/Backspace/Delete/курсора работает некорректно. Это связано с тем, что абсолютное большинство консольных приложений использует readline и корректная настройка этих кнопок считывается из /etc/inputrc и ~/.inputrc , а zsh этого не делает.
Проблема решается в лоб — нужно посмотреть, какие escape-последовательности выдают нужные кнопки в вашем терминале и задать в ~/.zshrc нужные обработчики для этих escape-последовательностей. Примерно так:
bindkey '^[[A' up-line-or-history # Up bindkey '^[[B' down-line-or-history # Down # и т.д.
Смотреть выдаваемые кнопками последовательности можно запустив cat >/dev/null и нажимая Ctrl-V перед нужной кнопкой. (И таки да, занимаясь этим в 2017 я чувствовал себя немного странно…) Но в комплекте с zsh идёт вспомогательная утилита zkbd , которая автоматизирует этот процесс. Для этого необходимо подключить её в ~/.zshrc , после чего у вас появится ассоциативный массив $key содержащий нужные escape-последовательности:
autoload -Uz zkbd [[ ! -f ~/.zkbd/$TERM-$:-$VENDOR-$OSTYPE> ]] && zkbd source ~/.zkbd/$TERM-$:-$VENDOR-$OSTYPE> [[ -n $key[Up] ]] && bindkey -- $key[Up] up-line-or-history [[ -n $key[Down] ]] && bindkey -- $key[Down] down-line-or-history # и т.д.
Я не уточняю детально какие команды (вроде up-line-or-history ) на какие кнопки назначать потому, что во-первых назначать надо не все подряд, а только те, которые у вас из коробки не заработают, и во-вторых если мнения насчёт того, что должны делать Home или Backspace у всех сходятся, то вот поиск в истории по Up и Down может выполняться довольно разными способами, и функции в этих случаях на эти кнопки надо назначать тоже разные.
(Кстати, задавать символ Escape ( ^[ ) в параметре bindkey можно и настоящим символом, вводя его через Ctrl-V , и двумя обычными символами ^[ , и двумя символами \e .)
zstyle
Это встроенный способ использовать контекстно-зависимые настройки. Он во многом похож на обычные параметры, только помимо имени и значения параметра zstyle позволяет задать шаблон «контекста». А потом получать значения относящиеся к текущему контексту. Этот подход активно используется для настройки работы автодополнений, но им можно пользоваться и для своих скриптов.
# установим значение my-param=default для 3-х уровневого контекста, # где на первом уровне идентификатор нашего приложения (у всех # приложений общая база zstyle, так что свои настройки надо изолировать) # а на следующих двух уровнях любые значения % zstyle ':my-app:*:*' my-param default # установим значение my-param=val-one для контекста, у которого на # втором (более приоритетном) уровне будет значение "one" % zstyle ':my-app:one:*' my-param val-one # установим значение my-param=val-two для контекста, у которого на # третьем (менее приоритетном) уровне будет значение "two" % zstyle ':my-app:*:two' my-param val-two # получаем значение my-param в переменную result для заданного контекста % zstyle -s ':my-app:a:b' my-param result % echo $result default % zstyle -s ':my-app:one:b' my-param result % echo $result val-one % zstyle -s ':my-app:a:two' my-param result % echo $result val-two % zstyle -s ':my-app:one:two' my-param result % echo $result val-one
zmodload
Часть дополнительного функционала zsh реализована не в обычных скриптах подгружаемых через autoload -Uz , а как системные библиотеки *.so . Они используются, например, для предоставления доступа к регулярным выражениям PCRE, математическим функциям, сокетам, etc. Такие библиотеки подгружаются через zmodload .
Разное
Для перехвата сигналов помимо стандартного trap ‘…;code;…’ INT можно использовать функции с особыми именами: TRAPINT() < …;code;… >.
У многих конструкций вроде if , while , etc. есть сокращённая форма (пример есть выше, где выводилось значение всех режимов bindkey).
Внезапно, zsh-специфичный аналог echo — команда print — оказалась весьма удобной при изучении zsh. Она много чего умеет, но из самого полезного:
# вывод по одному аргументу на строку, удобно для массивов print -l $path # вывод по два аргумента на строку в столбцах, # удобно для ключей и значений ассоциативных массивов print -a -C 2 "$" | sort # вывод используя %-последовательности используемые в $PS1 print -P '%Bbold%b %Fcurrent%f dir is: %~'
Если Когда решитесь переходить на zsh, то для принятия конкретных решений про фреймворки/модули/темы вам пригодится Awesome-коллекция всего для zsh.
Обзор-сравнение командных оболочек (unix shell): BASH, ZSH, FISH
Unix shell — это оболочка (интерпретатор команд), предоставляющая пользовательский интерфейс командной строки для Unix подобных операционных систем. Оболочка одновременно является языком интерактивных команд и языком сценариев (скриптов) и используется пользователем для передачи команд (списка команд) операционной системе.
Название BASH происходит от «Bourne again shell» (еще одна командная оболочка Борна). Появилась в 1987 году, как усовершенствованный вариант командной оболочки Bourne shell (sh, автор Стивен Борн). Поскольку фамилия Bourne (Борн) созвучна со словом born (рожденный), появился каламбур «Born again shell» (рожденная вновь командная оболочка).
BASH, как и все shell, представляет собой командный процессор, работающий в текстовом окне в интерактивном режиме. Поддерживает различные сокращения и переменные, операторы цикла, контроль и подстановку вывода результатов, автодополнение имен файлов и каталогов. Синтаксис BASH и другие особенности языка были заимствованы его автором Брайаном Фоксом из SH.
BASH — одна из первых программ, которую Линус Торвальдс (создатель Linux) портировал на Linux. BASH — самая распространенная оболочка Linux и каждый пользователь, который хоть раз открывал терминал, взаимодействовал с ней.
Ключевые особенности BASH:
- Огромное количество пользователей используют BASH, так как эта оболочка установлена по умолчанию в большинстве систем Linux
- Командный процессор BASH имеет множество встроенных команд
- BASH не имеет встроенного выражения с подстановочными знаками (*,?,[]), которые используются для поиска шаблонов, аналогично регулярному выражению
- Символ # рассматривается как комментарий в сценарии BASH
- Имеет крайне скромные (ограниченные возможности) настройки
- Пользовательские параметры конфигурации находятся в домашнем разделе в файле /home/.bashrc
Первая версия ZSH была написана Паулем Фалстадом, когда он был студентом Принстонского университета в 1990 году. Название оболочки произошло от учетной записи «zsh» университетского ассистента Пауля по имени Чжун Шао. В настоящее время проект развивается энтузиастами под руководством Питера Стефенсона в рамках свободно распространяемого ПО.
ZSH является расширенным аналогом BASH и имеет с ним обратную совместимость, добавляя ему большое количество улучшений.
Ключевые особенности ZSH:
- Встроенное автозаполнение с расширенным функционалом. Клавиша TAB ⇆ используется для автоматического дополнения (завершения) любой команды, которую вы хотите запустить. Помимо автозаполнения она выводит раскрывающийся список всех возможных файлов и каталогов
- Поддерживает встроенные выражения с подстановочными знаками (*, ?, [])
- Более настраиваемый, чем BASH
- Поддерживает различные плагины, расширяющие функционал и темы для кастомизации внешнего вида.
- Oh My Zsh — наиболее известный фреймворк для применения разнообразных настроек оболочки
- Пользовательские параметры конфигурации находятся в домашнем разделе в файле /home/.zshrc
FISH — это POSIX несовместимая оболочка UNIX с упором на интерактивность и удобство использования, была создана Акселем Лильенкранцем в 2005 году. POSIX (Portable Operating System Interface) — набор стандартов, описывающих интерфейсы между операционной системой и прикладной программой (системный API), библиотеку языка «C» и набор приложений и их интерфейсов.
В отличие от других оболочек, которым требуется много настроек и дополнительных плагинов, FISH предлагает все удобства пользователю прямо «из коробки». В то же время FISH является самой нестандартной оболочкой из-за того, что она не соответствует POSIX.
Синтаксис в FISH также изменен в сторону упрощения командного языка оболочки, например все управляющие конструкции завершаются ключевым выражением «end». Еще одним нововведением FISH являются универсальные переменные, вводимые с помощью конструкции «set -U переменная значение».
Ключевые особенности FISH:
- FISH предлагает автоматический «поиск во время ввода», основанный на истории команд и каталоге, в котором вы находитесь на момент ввода
- Встроенная подсветка синтаксиса — это функция, которую мы все хотели бы иметь в интерфейсе командной строки. Это делает работу проще и удобней, экономит много времени. И все это предлагается пользователю прямо «из коробки», интерфейс выглядит красиво и интуитивно понятно
- FISH умеет анализировать справочные страницы MAN и преобразовывать их в табличный формат вывода с удобным перемещением между данными
- Настройки FISH очень просты и понятны. Для изменения внешнего вида достаточно набрать в окне терминала команду: «fish_config», — откроется веб-сервис настроек, с возможностью выбора уже готовой предустановки, либо любой пользовательской конфигурации
- Дополнительно для расширения возможностей и настроек кастомизации FISH предлагается фреймворк Oh My Fish, аналогичный таковому в ZSH
- FISH предлагает очень простой и интуитивно понятный интерфейс командной строки для любого пользователя любого уровня. Для вызова справки по командному процессору FISH нужно просто набрать «help» в окне терминала, — откроется веб-сервис с удобно организованной и хорошо наполненной интерактивной базой знаний, в которой точно «найдется все»
- Пользовательские параметры конфигурации находятся в домашнем разделе в файле /home/.config/fish/config.fish
Демонстрация особенностей
Выводы
- BASH, ZSH и FISH имеют свои достоинства и недостатки, а также некоторые сходства между собой
- Если вы консерватор и приверженец всего классического, вы просто можете оставить себе BASH
- Если вы хотите что-то более гибкое и настраиваемое, вы можете попробовать ZSH, дополнив его плагинами или даже установив Oh My Zsh
- Если вам нужен интерактивный терминал без особых настроек, вы можете смело использовать FISH. Даже если он и не лучший во всем, FISH имеет функциональные возможности, соответствующие основной философии UNIX: «Do one thing, and do it well” (делай что-то одно и делай это хорошо)
Вместо послесловия
Если спросить мое личное мнение, то я предложу FISH, несмотря на то, что сам использую ZSH 🙂
В чём Разница между fish, zsh, bash, sh, csh, dash,
Добрый день, я бы хотел узнать, какие отличия между fish и другими оболочками. Возможность есть отличия в скорости, или переменные окружения другие, синтаксис, автодополние? Мне интересно, ведь, например nixos package manager несовместим с fish.
WinUsers
09.11.21 18:58:37 MSK
Возможность есть отличия в скорости, или переменные окружения другие, синтаксис, автодополние?
cocucka ★★★★☆
( 09.11.21 19:09:19 MSK )
- Fish — наркоманский синтаксис, несовместимый с POSIX, но значительная часть функциональности просто работает из коробки. Остальное легко добавляется небольшим количеством дополнений. Работает почти идеально и есть не просит.
- Zsh — старше fish, (почти) POSIX-совместима. Также имеет обширную функциональность, сторонняя поддержка больше, чем у fish. Но чтобы добиться аналогичной fish функциональности, нужно приложить гораздо больше усилий, при этом всё равно так же хорошо работать не будет.
- Bash — говно мамонта. Есть приблуды, чтобы придать ему человеческое лицо, но работают они ещё более криво, чем в zsh.
sudopacman ★★★★★
( 09.11.21 19:16:09 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:16:09 MSK
А можно как-то сделать fish posix совместиным? Работает он намного лучше zsh, и не так ограничен в функционале, как bash.
WinUsers
( 09.11.21 19:18:43 MSK ) автор топика
Ответ на: комментарий от WinUsers 09.11.21 19:18:43 MSK
это и не нужно, просто юзай баш для сторонних скриптов а фиш для работы в консоле и своих скриптов. юзаю фиш уже пару лет
TDrive ★★★★★
( 09.11.21 19:20:53 MSK )
Ответ на: комментарий от TDrive 09.11.21 19:20:53 MSK
Мне нужно, я указал выше, что fish несовместим с nixpm.
WinUsers
( 09.11.21 19:23:09 MSK ) автор топика
Ответ на: комментарий от WinUsers 09.11.21 19:18:43 MSK
А можно как-то сделать fish posix совместиным?
Разве что свой форк запилить.
На самом деле в командной строке это не так важно. Главное не менять login shell для пользователя через chsh , а выбрать fish в настройках эмулятора терминала.
!! и !$ добавляются плагином, при этом замена производится сразу, а не после нажатия Enter, что намного удобнее, чем в bash.
sudopacman ★★★★★
( 09.11.21 19:25:35 MSK )
Ответ на: комментарий от WinUsers 09.11.21 19:23:09 MSK
не пользовался, но это странно что программа зависят от интерпретатора юзера. Может написать авторам?
TDrive ★★★★★
( 09.11.21 19:26:17 MSK )
Use bash, Luke
bash — есть практически везде и достаточно удобен. Много документации по нём Идеальный балланс.
sh — есть вообще везде, но не столь удобен.
Остальные не так распространены и разной степени нестандратны
Kroz ★★★★★
( 09.11.21 19:27:00 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:25:35 MSK
у меня фиш в /etc/passwd прописан и даже для рута, не ловил каких то проблем с этим
TDrive ★★★★★
( 09.11.21 19:27:17 MSK )
Ответ на: комментарий от TDrive 09.11.21 19:26:17 MSK
Нет, тут проблема в том, что этот пакетный менеджер требует определенных переменных окружения, а синтаксис для изменения этих переменные в fish несовместим с bash, под который nixpkg заточен. Поэтому автостарт nixpkg просто не работает с рыбой.
WinUsers
( 09.11.21 19:29:39 MSK ) автор топика
Ответ на: комментарий от WinUsers 09.11.21 19:29:39 MSK
я бы написал алиас который будет запускать его в баше
TDrive ★★★★★
( 09.11.21 19:30:46 MSK )
Ответ на: комментарий от TDrive 09.11.21 19:27:17 MSK
А как же /etc/profile , ~/.bash_profile , /etc/bash.bashrc , ~/.bashrc и прочие скрипты автозапуска?
sudopacman ★★★★★
( 09.11.21 19:31:14 MSK )
Ответ на: комментарий от TDrive 09.11.21 19:30:46 MSK
Можно, надо будет попробовать.
WinUsers
( 09.11.21 19:31:23 MSK ) автор топика
Ответ на: комментарий от WinUsers 09.11.21 19:29:39 MSK
У меня всё работало с bash в качестве login shell и fish в эмуляторе терминала.
sudopacman ★★★★★
( 09.11.21 19:32:00 MSK )
annulen ★★★★★
( 09.11.21 19:32:37 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:31:14 MSK
ну на баш профайл пофиг, а /etc/profile не вызывает проблем. это рабочий ноут, а не сервер если че.
TDrive ★★★★★
( 09.11.21 19:32:49 MSK )
Zubok ★★★★★
( 09.11.21 19:33:08 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:31:14 MSK
Дело в том, что я устанавливаю fish, через chsh(так рекомендовано в archwiki). Поэтому естественно .bashrc и другие не работают. Да, вы мне, как раз посоветовали установить его через эмулятор терминала по умолчанию.
WinUsers
( 09.11.21 19:33:19 MSK ) автор топика
Ответ на: комментарий от TDrive 09.11.21 19:30:46 MSK
Тут ещё стоит отметить плагин bass (и аналоги).
sudopacman ★★★★★
( 09.11.21 19:33:22 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:33:22 MSK
А, ну вот, тогда вообще проблем нету, не знал про этот плагин.
TDrive ★★★★★
( 09.11.21 19:35:53 MSK )
Ответ на: комментарий от sudopacman 09.11.21 19:33:22 MSK
Плагин для шелла. Вот, меня устраивает.
WinUsers
( 09.11.21 19:36:17 MSK ) автор топика
Последнее исправление: WinUsers 09.11.21 19:36:33 MSK (всего исправлений: 1)
Ответ на: комментарий от WinUsers 09.11.21 19:29:39 MSK
Попробуй добавить в конфиг системы programs.fish.enable = true; .
Tsukasa ★
( 09.11.21 19:41:15 MSK )
Последнее исправление: Tsukasa 09.11.21 19:48:11 MSK (всего исправлений: 1)
Ответ на: комментарий от WinUsers 09.11.21 19:18:43 MSK
najlus ★★★★★
( 09.11.21 19:42:23 MSK )
Если часто пишешь скрипты (как это делаю я), то лучше сидеть bash , так как не приходится держать в голове сразу два синтаксиса: синтаксис какой-то другой оболочки + bashевский, который всё равно нужен.
Если дофига хакер, то нужно сидеть в zsh и хвастаться на ЛОРе и гитхабе, как ты его круто настроил.
Ну а если консоль нужна редко, то сойдёт и fish .
Про остальные, если интересно:
dash — быстрая и очень урезанная оболочка, чтобы запускать скрипты быстрее. Совместима с POSIX, но не поддерживает фишки bash .
csh мёртв. tcsh , если вдруг где попадётся, — тоже мёртв.
wandrien ★★
( 09.11.21 19:46:32 MSK )
Ответ на: комментарий от wandrien 09.11.21 19:46:32 MSK
dash — быстрая и очень урезанная оболочка, чтобы запускать скрипты быстрее.
Это не совсем так. Есть что работает быстрее, но bash потому и толстый, что на каждую конструкцию применяется своя функциональная реализация, которая работает быстрее по принципу смещения баланса память=код/размер. Но и даже если что-то интерпретируется быстрее, то надо понимать, что на bash код мощнее, а это для интерпретаторов очень важно, так как внутренности то работают на C.
vodz ★★★★★
( 09.11.21 20:06:47 MSK )
Ответ на: комментарий от vodz 09.11.21 20:06:47 MSK
Не понял, что ты имеешь ввиду.
apt_install_lrzsz ★★
( 09.11.21 20:58:08 MSK )
Ответ на: комментарий от wandrien 09.11.21 19:46:32 MSK
Пока есть возможность спрошу, можно в bash поведение ^W сделать как в ksh?
RebHat
( 09.11.21 21:29:44 MSK )
Ответ на: комментарий от RebHat 09.11.21 21:29:44 MSK
А какое там поведение?
wandrien ★★
( 09.11.21 21:30:30 MSK )
Ответ на: комментарий от wandrien 09.11.21 21:30:30 MSK
пример, допустим есть путь /home/user/emacs/etc
баш при нажатии ^W удалит весь путь, кш до первого знака, только etc
RebHat
( 09.11.21 21:39:15 MSK )
Ответ на: комментарий от RebHat 09.11.21 21:39:15 MSK
Хм, у меня не получается забиндить unix-filename-rubout на C-w. Он просто игнорирует этот bind, будто его нет:
"\C-b": unix-filename-rubout "\C-w": unix-filename-rubout
wandrien ★★
( 09.11.21 22:07:08 MSK )
Ответ на: комментарий от wandrien 09.11.21 22:07:08 MSK
спасибо за подсказку, пойду в гугл поищу.
дернул черт опенка попробовать, пришлось другой шелл ставить. в баш конечно работает Alt+Backspace , но это неудобно весьма.
RebHat
( 09.11.21 22:17:17 MSK )
Ответ на: комментарий от apt_install_lrzsz 09.11.21 20:58:08 MSK
То, что на bash можно сделать одной командой, на posix shell придётся делать большим и медленным скриптом: массивы, обработка строк, регулярки. Есть вещи, которые сделать на dash практически не возможно — обработка вывода команд с zero-char разделителем записей, статус обоих команд pipe.
vodz ★★★★★
( 09.11.21 22:29:59 MSK )
Ответ на: комментарий от wandrien 09.11.21 22:07:08 MSK
это для меня сработало:
stty werase undef bind "\C-w":unix-filename-rubout
благодарю за подсказку
RebHat
( 09.11.21 22:53:43 MSK )
Ответ на: комментарий от RebHat 09.11.21 22:53:43 MSK
wandrien ★★
( 09.11.21 22:56:34 MSK )
А еще ksh был. Кто помнит? Мой любимый шел был тогда, в NetBSD 1.6 🙂
Вроде как все шелы обратно совместимы с борн шел aka sh. Хотя кто эти новомодные глисты знает, завелись и не выведешь теперь.
untitl3d ★
( 09.11.21 23:02:03 MSK )
Ответ на: комментарий от untitl3d 09.11.21 23:02:03 MSK
Не застал. Ставил как-то недавно, почитал мануал. Нашел несколько фич, отсутствующих в bash. Подивился да вернулся в bash.
wandrien ★★
( 09.11.21 23:04:17 MSK )
Ответ на: комментарий от wandrien 09.11.21 22:56:34 MSK
елки, похоже я поторопился с ответом(
после релога не работает клавиша «s».
RebHat
( 09.11.21 23:19:55 MSK )
Ответ на: комментарий от wandrien 09.11.21 22:56:34 MSK
set bind-tty-special-chars off "\C-w": unix-filename-rubout "\e\C-?": unix-word-rubout
RebHat
( 09.11.21 23:49:08 MSK )
Ответ на: комментарий от WinUsers 09.11.21 19:23:09 MSK
Что эти слова вместе значат? Ты его как дефолтный шелл в stdenv пихаешь или как? Как шелл может быть несовместим с PM?
t184256 ★★★★★
( 09.11.21 23:52:45 MSK )
какие отличия между fish и другими оболочками. Возможность есть отличия в скорости, или переменные окружения другие, синтаксис, автодополние?
Гигантские, но они при этом все нестандартны и ужасны. Юзай xonsh, там хоть ЯП настоящий.
t184256 ★★★★★
( 09.11.21 23:55:44 MSK )
Мне интересно, ведь, например nixos package manager несовместим с fish.
Кот не совместим? Всё совместимо.
anonymous
( 10.11.21 10:55:23 MSK )
Возможность есть отличия в скорости
какая разница, какая скорость в интерактивной оболочки? А для скриптов длиннее однострочников они все более-менее сравнимое говно
anonymous
( 10.11.21 15:00:54 MSK )
sh это просто название файла, но обычно подразумевается, что под этим названием будет POSIX-совместимый шелл, по идее оно должно быть во всех unix-ах в т.ч. в линуксах
dash это реализация POSIX-совместимого шелла из дебиана, для запуска под именем /bin/sh
bash это почти POSIX шелл, есть в большинстве линуксов как дефолтный интерактивный шелл, в некоторых он к сожалению преподносится ещё и как /bin/sh, от чего неграмотные юзеры начинают писать для него скрипты. Некоторые извращенцы пишут скрипты для баша, даже зная что это не /bin/sh, ставят в начале #!/bin/bash
csh — дефолтный интерактивный шелл FreeBSD, довольно удобный в качестве интерактивного, для скриптов (как и баш) лучше не использовать но некоторые пишут
zsh fish и ещё куча разных *sh — нестандартные шеллы для любителей, их много разных, разбираться в них незачем