Right, let’s settle this. You’re staring at a terminal, and you’ve probably heard the whispers: “bash is the standard,” “zsh has better completion,” “just install Oh My Zsh and be done with it.” It’s not a holy war, it’s a toolkit upgrade. I use both daily, and here’s the unvarnished truth about what separates them and how to choose.

The Glorious, Game-Changing Autocomplete

This is the single biggest reason people switch. bash’s completion is… fine. It tries. zsh’s is like it has a psychic link to your intentions.

In bash, you type cp ~/Down and hit Tab. It completes to ~/Downloads/. Great. Now you want to copy a file from deep inside that directory. You type cp ~/Downloads/Project/Code/main and hit Tab. Nothing. It’s confused. You have to hit Tab again to list possibilities or manually type the rest.

Now watch zsh do its party trick. Same scenario: cp ~/Down -> Tab -> ~/Downloads/. Now type /P -> Tab. It expands to ~/Downloads/Project/. /C -> Tab -> ~/Downloads/Project/Code/. /main -> Tab. It completes the filename, even if there’s a main.c and main.h, it will list them for you. It’s path-aware completion. You’re not just completing strings; you’re navigating your filesystem logically.

But wait, there’s more. Want to kill a process? Just type kill vim and hit Tab. zsh will expand vim to the actual PID. It’s absurdly helpful.

# In zsh, this is magic
$ kill chrom Tab # expands to 'kill 1234'

bash can be taught these tricks with enough configuration (see bash-completion package), but zsh gives it to you out of the box. It’s the difference between building a race car and buying one that’s already tuned.

The Mystery of the Missing Dollar Sign and Other Syntax Sugar

zsh quietly fixes some of bash’s more… verbose syntax. The most famous one is that in zsh, you don’t always need ${} to dereference variables. You can often just use $.

# bash: This is safe and explicit, but clunky.
filename="document"
echo "${filename}.txt"

# zsh: This just works. It knows 'filename' is the variable.
echo "$filename.txt"

Now, before you get too excited, I have to be direct: This is a trap. It’s convenient until you write a script that needs to run on literally any other system (which probably has bash). Relying on this will bite you. Consider it a nice-to-have for your interactive shell, but don’t use it in scripts you plan to share.

zsh also supports floating-point math natively, while bash is stubbornly integers-only.

# zsh can do this
$ echo $(( 10 / 3.0 ))
3.3333333333333333

# bash chokes on it
$ echo $(( 10 / 3.0 ))
bash: 10 / 3.0: syntax error: invalid arithmetic operator (error token is ".0")

The Power of Plugins and Frameworks

This isn’t a core feature of zsh, but it’s the ecosystem that grew around its extensibility. Oh My Zsh isn’t just a theme; it’s a plugin manager and configuration framework that makes zsh’s powerful features accessible.

Want to have your prompt show the status of your git repo? There’s a plugin for that. Want to type git and hit Tab to see all possible commands and flags? There’s a plugin for that. Want to automatically cd into a directory by just typing its name? There’s a plugin for that (autocd is actually a built-in zsh option that Oh My Zsh enables).

bash has frameworks too (bash-it), but they don’t feel as integral to the experience. The zsh community leaned into this hard, and it shows.

So, Which One Should You Use?

Here’s my brutally honest advice:

  • Stick with bash if: You live on servers. You write portable shell scripts that need to run anywhere. You value universality and stability over flashy features. Your .bashrc is a sacred text you’ve curated over a decade and you see no reason to change.

  • Switch to zsh if: You spend most of your time on your own machine (like a Mac, where it’s been the default since Catalina). You crave a more intelligent, fluid interactive experience. You’re not afraid to use a framework like Oh My Zsh or Prezto to manage the complexity. You value your time and want tab-completion that doesn’t hate you.

The best part? It’s not a permanent choice. Your login shell is just a setting in /etc/passwd or with chsh. You can have your bash for scripting and zsh for interactive use. Or vice versa. The point is to understand the tools and then use the one that makes you more effective. Now stop reading about it and go try it. Type zsh in your terminal and see for yourself.