Zsh vs bash, and switching

Zsh · Essentials · 7 min

You need to know which shell is reading your commands before any configuration makes sense.

Zsh is a Bourne-family shell, so everyday command lines, pipes, redirections, variables, if and for work as in bash. What it adds is mostly for interactive use: a far smarter completion system, recursive globbing with filters, spelling correction, shared history, a programmable line editor and prompt, and a big plugin ecosystem. It has been the default login shell on macOS since 10.15 Catalina; on Linux you install it with your package manager.

Two variables are easy to confuse. $SHELL is your login shell as recorded in the user database, not necessarily the shell you are running right now; ps -p $$ or echo $ZSH_VERSION tells you the current one. Change your login shell with chsh -s "$(command -v zsh)"; the path must be listed in /etc/shells, and the change applies at your next login.

The first time zsh starts without a ~/.zshrc it offers the zsh-newuser-install menu; you can quit it and write the file yourself. zsh -f starts a shell with no startup files, handy for testing whether a problem comes from your config.

Switching your interactive shell does not change scripts: a script with #!/usr/bin/env bash keeps running under bash. Keep writing portable scripts in bash or sh, and use zsh for your terminal.

Example

zsh --version                 # zsh 5.9 (x86_64-pc-linux-gnu)
echo $SHELL                   # login shell from the user database, e.g. /bin/zsh
ps -p $$ -o comm=             # the shell you are actually in: zsh
echo $ZSH_VERSION             # 5.9  (empty in bash)
grep zsh /etc/shells          # /bin/zsh /usr/bin/zsh  (allowed for chsh)
chsh -s "$(command -v zsh)"   # make zsh your login shell; log in again
zsh -f                        # a clean zsh with no config files
./deploy.sh                   # a #!/usr/bin/env bash script still runs in bash

Remember

  • Zsh is Bourne-compatible for everyday use and adds interactive features
  • $SHELL is the login shell; ps -p $$ shows the current shell
  • chsh -s changes the login shell; scripts follow their shebang

Watch out for

  • Assuming $SHELL tells you which shell is running right now.

Check yourself

  1. You switched your terminal to zsh. Which shell runs a script whose first line is #!/usr/bin/env bash?
  2. What is `zsh -f` useful for?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: zsh.sourceforge.io/Doc/Release/Invocation.html