bash vs zsh vs fish - Choosing the Right Shell for You
Which Shell Should You Choose?
The answer depends on your use case.
- bash — scripts, server administration, maximum portability
- zsh — comfortable daily interactive use with strong bash compatibility (macOS default)
- fish — best out-of-the-box completions and highlighting with zero configuration
If portability matters (scripts, shared servers), bash is the clear choice. If you want a great interactive experience without spending time on configuration, fish gets you there immediately. zsh sits in the middle — compatible with bash while offering a rich plugin ecosystem.
What is bash?
bash (Bourne Again Shell) is the default shell on nearly every Linux distribution and was macOS's default until 2019. It offers the highest POSIX compatibility and is the most portable option for shell scripting.
echo $BASH_VERSION
5.2.21(1)-release
Key characteristics:
- Ships on virtually every Unix/Linux system by default
- High POSIX sh compatibility
- Minimal interactive features without configuration (no syntax highlighting, basic tab completion)
- Enormous library of existing scripts and documentation
Use bash for any script you want to run reliably across different systems. #!/bin/bash is the most universal shebang line.
Bash's interactive experience can be improved by installing bash-completion, but it still trails zsh and fish in day-to-day usability.
What is zsh?
zsh (Z shell) is designed as an extended bash with enhanced interactive features. Apple switched macOS's default shell from bash to zsh in Catalina (2019), which significantly boosted its adoption.
echo $ZSH_VERSION
5.9
Key characteristics:
- Runs most bash scripts without modification
- Powerful built-in completion system
- Rich ecosystem: Oh My Zsh, Powerlevel10k, hundreds of plugins
- Extended glob patterns, spelling correction, right-side prompt (RPROMPT)
If you're migrating from bash, zsh is low-friction — most existing scripts run as-is. This is one of the main reasons it's recommended as a step up from bash.
Adding Oh My Zsh unlocks hundreds of plugins and themes, but be aware that a heavily configured setup can slow down shell startup times noticeably.
What is fish?
fish (Friendly Interactive Shell) is built around the principle of "works great out of the box." Syntax highlighting, autosuggestions, and man-page-based completions are active immediately after installation — no configuration needed.
echo $version
3.7.1
Key characteristics:
- Real-time syntax highlighting as you type (valid commands in white, unrecognized commands in red)
- History and man-page based autosuggestions enabled by default
- Configuration at
~/.config/fish/config.fish - Not POSIX-compatible — uses its own unique syntax
Fish syntax is incompatible with bash/zsh. Standard patterns like VAR=value, if [ ... ], and export do not work in fish. Use fish for interactive sessions and keep bash for scripts that need to run elsewhere.
How do bash, zsh, and fish compare?
| Feature | bash | zsh | fish |
|---|---|---|---|
| Default on | Linux distros | macOS | None |
| bash compatibility | — | High | Low |
| Tab completion | Basic | Powerful | Best |
| Syntax highlighting | Requires setup | Requires setup | Built-in |
| Autosuggestions | None | Plugin required | Built-in |
| Configuration cost | Low | Medium–High | Low |
| Script portability | Best | High | Low |
| Plugin ecosystem | Minimal | Large (OMZ) | fisher |
| POSIX compliance | High | High | Low |
When should you use each shell?
Server administration and DevOps
Use bash. Script portability and availability on remote systems are the priority. Most production servers won't have fish or zsh installed, and relying on a non-standard shell in automation scripts is a reliability risk.
#!/bin/bash
# Scripts meant to run across servers should use bash
set -euo pipefail
DEPLOY_DIR="/var/www/app"
echo "deploy started: ${DEPLOY_DIR}"Daily interactive use (macOS or WSL)
zsh or fish. On macOS, zsh is already the default — adding Oh My Zsh or Powerlevel10k gives you a highly productive setup in minutes. Fish is the faster path if you want good completions and syntax highlighting with zero configuration.
# Switch default shell to zsh chsh -s /usr/bin/zsh # Switch default shell to fish (if installed) chsh -s /usr/bin/fish
Learning Linux for the first time
Start with bash. Most tutorials, books, and online examples assume bash. Learning fish first creates a knowledge gap when you encounter bash-based scripts or documentation.
How do you check and change your shell?
Check your current shell
echo $SHELL
/bin/bash
You can also check the running process name:
ps $$
PID TTY STAT TIME COMMAND 12345 pts/0 Ss 0:00 -bash
List available shells on your system
cat /etc/shells
/bin/sh /bin/bash /usr/bin/bash /bin/rbash /usr/bin/rbash /usr/bin/sh /bin/dash /usr/bin/dash /usr/bin/zsh /bin/zsh
Change your default shell
# Switch to zsh chsh -s /usr/bin/zsh # Switch to fish (if installed) chsh -s /usr/bin/fish
chsh takes effect at the next login or terminal restart — it does not change your current session. Verify with echo $SHELL after restarting the terminal.
If fish is not installed, add it with:
# Ubuntu / Debian sudo apt install fish # macOS (Homebrew) brew install fish
Common misconceptions
"zsh is faster than bash" — Startup speed depends on your configuration. A heavily-plugged Oh My Zsh setup is often slower than vanilla bash. Measure your zsh startup time with time zsh -i -c exit.
"fish can't be scripted" — Fish has its own scripting language, but it's incompatible with bash/POSIX sh. Fish scripting works well for fish-specific functions and completions; for portable automation, use bash.
"bash is outdated" — For interactive use, zsh and fish offer a better experience. For server automation, CI/CD pipelines, and portable scripts, bash's stability and ubiquity remain genuine strengths. Choose based on the task, not trends.