Bash vs Zsh vs Fish: какой shell выбрать
В прошлом уроке мы установили, что shell — это программа-интерпретатор, и их несколько на выбор. Сегодня — детальное сравнение трёх главных вариантов на 2026 год: Bash 5.3, Zsh (с oh-my-zsh) и Fish 4. Цель — понять, какой выбрать для интерактивной работы, а на каком писать скрипты.
Спойлер: на чём писать скрипты — на Bash (везде работают). Что использовать interactive — выбор зависит от вкуса.
Bash 5.3 — стандарт де-факто
Bash (Bourne Again SHell) — это GNU-реализация Bourne Shell, написанная Brian Fox в 1989. С тех пор развивается командой GNU. Последний крупный релиз — bash 5.3 (июль 2025).
Что нового в bash 5.3 (июль 2025):
- Улучшенная производительность
[[ ... ]]тестов; - Новая встроенная команда
wait -nс улучшенной обработкой сигналов; - Поддержка
BASH_REMATCHдля multi-line regex; - Множество мелких bugfix-ов в
read,printf,mapfile.
На большинстве Ubuntu 26.04 и Debian 13 у вас будет именно bash 5.3. На macOS системный bash — всё ещё 3.2 (2007 год!), нужно ставить через brew.
$ bash --version
GNU bash, version 5.3.0(1)-release (x86_64-pc-linux-gnu)
Zsh — bash на стероидах
Zsh (Z Shell) появился в 1990, активно развивается. Главная идея: совместимость с bash + улучшения. Большинство bash-скриптов работают в zsh без изменений. Но zsh даёт больше для интерактивной работы.
Главный фреймворк для zsh — oh-my-zsh. Это open-source проект, который добавляет zsh:
- 300+ плагинов (git, docker, kubectl, python venv, autosuggestions);
- 100+ тем (от минималистичных до с цветами и иконками);
- Удобная установка и обновление.
# Установка oh-my-zsh
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
После установки настройка идёт через ~/.zshrc. Плагины — добавление имён в строку plugins=(git docker).
Лучшая тема для DE — Powerlevel10k. Показывает в prompt: ветку git, статус (clean/dirty), Python venv, k8s context, время выполнения предыдущей команды. Настраивается интерактивным wizard за 2 минуты.
Современная альтернатива oh-my-zsh — starship. Это prompt, написанный на Rust, кросс-shell (работает в bash, zsh, fish, nushell), супер-быстрый. Все DE-фичи (git, kube, venv) — из коробки. Один config (~/.config/starship.toml) переносится между машинами. Многие сейчас переходят на starship: oh-my-zsh для совместимости, prompt от starship.
Fish — friendly out of the box
Fish (Friendly Interactive SHell) — это третий путь. Главная философия: «должно работать из коробки, без часовой настройки». Никаких oh-my-fish (хотя есть), всё уже встроено.
Пример различия синтаксиса:
# Fish: переменные присваиваются через `set`, не `=`
> set name "Alice"
> echo $name
Alice
# bash/zsh
$ name="Alice"
$ echo $name
Alice
# Fish: функции
function greet
echo "Hello $argv[1]"
end
greet "Bob"
# bash/zsh
greet() {
echo "Hello $1"
}
greet "Bob"
Если попробуете запустить bash-скрипт в fish — упадёт почти сразу:
> bash -c 'for i in 1 2 3; do echo $i; done' # работает (это bash под капотом)
> for i in 1 2 3; do echo $i; done # фатально, fish не понимает синтаксис
fish: Expected end of statement, but found ';'
Что выбрать для DE
Простое правило:
Конкретные рекомендации:
- Скрипты — bash. Никогда не пишите production-скрипт на fish (никто кроме вас не запустит). Никогда не пишите на zsh-specific синтаксисе (массивы 1-indexed, word splitting) — на серверах может стоять только bash.
- Интерактив на ноуте — что нравится. Зейн-вариант: zsh + starship + autosuggestions + syntax-highlighting плагины. Минималистичный: bash + readline + кастомный PS1.
- На сервере в SSH — bash. Не ставьте zsh на каждый сервер, это лишний шум. Привыкайте работать в bash, чтобы на любом сервере чувствовать себя дома.
Shebang: какой shell запускает скрипт
Когда вы делаете ./script.sh, ядро не знает, что это shell-скрипт. Оно смотрит на первую строку файла — shebang.
#!/usr/bin/env bash
echo "Hello from bash"
#! (sh-bang) в начале файла говорит ядру: «запусти эту программу и передай ей файл как аргумент». Ядро запускает /usr/bin/env bash script.sh, и bash интерпретирует файл.
Разница между двумя вариантами:
Рекомендация: всегда #!/usr/bin/env bash. Это переносимо. Особенно важно на macOS, где /bin/bash — это древний 3.2, а нормальный bash живёт в /opt/homebrew/bin/bash или /usr/local/bin/bash.
$ cat > /tmp/test.sh <<'EOF'
#!/usr/bin/env bash
echo "Bash version: $BASH_VERSION"
EOF
$ chmod +x /tmp/test.sh
$ /tmp/test.sh
Bash version: 5.3.0(1)-release
Подробнее про chmod и executable bit — в модуле 6.
Что точно НЕ работает между shell
Несколько распространённых граблей:
-
Массивы. bash:
arr=(a b c); echo "${arr[0]}"(0-indexed). zsh: тоже работает, но zsh array по умолчанию 1-indexed (echo $arr[1]). fish: совсем другой синтаксисset arr a b c; echo $arr[1](1-indexed). -
Word splitting. bash:
var="a b"; for x in $var— разобьёт на два слова. zsh безsetopt SH_WORD_SPLIT— не разобьёт, оставит как одну строку. Это часто ломает скрипты при переносе из bash в zsh. -
$(< file). bash и zsh: читает файл целиком. fish: не работает, нужноcat fileилиread. -
localв функциях. bash/zsh:local var=foo. fish: нет concept of local, нужноset -l var foo.
Когда пишете production-скрипт, тестируйте на bash. Когда interactive — пишите что нравится, но осознавайте, что эти команды не перенесутся в shell-скрипт без переписывания.
Попробуй сам
Узнайте, какие shell установлены у вас и сравните:
$ cat /etc/shells
# Список разрешённых shell-ов на вашей системе
/bin/sh
/bin/bash
/usr/bin/bash
/bin/zsh
/usr/bin/zsh
# Какой у вас сейчас:
$ echo $0 # имя текущего shell
bash
# Переключиться в zsh (если установлен):
$ zsh
% echo $0
zsh
# Назад в bash:
% exit
Сравните, что отличается в подсветке и подсказках. На bash без oh-my-bash подсказок и подсветки не будет. На zsh с oh-my-zsh — будет.
Попробуйте установить starship (модерн prompt):
# Установка
$ curl -sS https://starship.rs/install.sh | sh
# Добавить в ~/.bashrc или ~/.zshrc:
$ echo 'eval "$(starship init bash)"' >> ~/.bashrc
$ source ~/.bashrc
Starship покажет в prompt: текущая директория, git-ветка, статус, активный Python venv, время выполнения.