My wife told me about this last year, but it didn’t really sink in until now: Apple replaces bash with zsh as the default shell in macOS Catalina.

Yuck!

When Apple first came out with a proper OS (for Macs) in 2001, the default shell was tcsh (The C Shell). This is actually the one used by people who were happily using Silicon Graphics workstations the previous ten years.

But zsh? Come on, that’s petulant. Bash is the standard.

The most important feature to consider when choosing a default shell is its prevalence. This is exactly why Apple relented and shifted to it a year after introducing OSX. The reason this is the top consideration and why Bash shines is that Bash is roughly an extension of the ancient classic sh shell. The ubiquitous sh. This is relied upon for many scripts and learning this is never a bad idea. Having it available is not an option — it will be mandatory. If you have learned it and you have it, why not leverage that? Sprinkle some upgrades with Bash (extending old-school sh) and that’s close to optimal.

Maybe some weird nerds have their good reasons to move away from Bash. Fine. That means they’re super fancy folks and they are obviously hard core experts at Bash, right? Because if you’re not, my advice would be to learn what you’re doing with Bash a bit better before thinking you’ve got a better plan. But let’s say you are an expert at Bash and you have Reasons. Well, you have your choice and as a hardened expert you can certainly run exotic shells like ksh or zsh or fish or ash or dash or go right from a Python interpreter or tcl/wish etc. For a similar example, last fall I started shifting over to use the Awesome Window Manager - not Gnome or KDE, etc. This doesn’t mean everyone should! I totally understand that my weirdo better-than-normal-people fantasy is mine alone. If you have that attitude about zsh, great, but don’t make it a default!

The fact is that zsh is not necessarily "better". I feel like it might help one to be clumsy with its particular portfolio of automagical features. Of course automagical features are all over Bash, mostly when you choose them to be.

When I look at why-zsh-is-so-great articles, I mostly see people who don’t know how to use Bash. The one exception is the zsh module system; I’m fine with Bash in this respect but if Bash maintainer Chet Ramey singles this out, I’ll take it seriously. I always assumed a "Bash module" was simply a separate executable. Problem solved.

A lot of the excitement seems to revolve around globbing and completion features that make me nervous because of their unavoidable overhead. Some (Ubuntu-esque) Bash setups have fancy parameter expansion (not merely executable and file argument expansion) because Bash is perfectly capable of such things. I however believe that something like man pyt<tab> should not complete; I find it insufferable how sluggish such features tend to be. If I’m logged into a slow Raspberry Pi on a ship at sea and I have a custom path with millions of files in it for some reason (which might be good), I don’t want to sit there for 5 minutes while it tries to correct my spelling (or indexes its db or whatever necessary trade off is enacted).

I think the most promising advantage to zsh is that it has floating point math. But Chet would sensibly argue that making your shell too heavy with no added functionality would lead to every process using a shell being weighed down. And I say "no added functionality" because Bash’s forte is passing jobs off to more competent systems. This is the classic Bash way — to punt off to a better tool as needed. Here’s Bash getting some floating point math done (by reassigning the task).

bash$ bc -l <<<"1/3.0"
.33333333333333333333

Bash wants you to have choices for things so assumes that if you need crazy floating point math, maybe you need it to be quite serious — maybe more serious than zsh’s 16 places:

zsh% print - $(( 1 / 3.0 ))
0.33333333333333331

Or maybe you can put awk to use. If you can, that’s probably good.

bash$ :|awk 'END{print 1/3}'
0.333333

How about this exotic variant?

bash$ dc<<<"30k 1 3 /p"
.333333333333333333333333333333

Not only am I getting arbitrary precision, but I’m able to use RPN too (30 on stack, set precision k, 1 on the stack, 3 on the stack, /, then print). And RPN just makes me happy.

Again, I’m emphasizing this because floating point ops are the only thing I’m sympathetic to with respect to zsh. The clumsy auto-corrections are mostly irritating to me (even completions in Bash are close to my limit). Even with the floating point "deficiency" I’m showing that Bash clearly has a plan.

What is unnerving is how many stock unix core systems come without bc these days. I always add it but that is an issue when it comes to Bash’s helper options.

That’s about it for technical details. There really is no compelling technical reason to choose any particular shell. Take your pick if you’re fancy. The real question here is the default and what subtle push is being made to promote one over the other. I suspect the facts are a bit more sinister. Ahem, Apple.

This article makes a pretty good case that the whole switch has been made by lawyers at Apple who are trying to resist very specific clauses of the GPL. I don’t read that stuff closely any more because I have come to completely trust Apple and companies like them — completely trust them to be asshats and do the wrong thing always. On the other hand, I completely trust the FSF to make a curmudgeonly GPL that will annoy most people most of the time, but be the right thing to do.

So booo to Apple if they’re really changing the default shell. Lame. I totally support and encourage people’s decision to use a weird shell, but a standard has already emerged. Messing with that does nobody any favors. Log into a Pi or an AWS instance or any Linux/SteamOS system, etc, etc, and it will be Bash. 18 years of Mac users know no different either. Really, is it a good idea to mess with that? I say no.

Stick with the wholesome classic. The command to set one’s shell in unix is usually chsh, "change shell". Something like this for my Linux.

chsh -s /usr/bin/bash

Or using some Bash features, helpful if you don’t know the path.

chsh -s $(which bash) ${USER}

Those expansions should work in Bash — and also zsh if you’re inadvertently stuck therein.

That’s the proper way to do things — using a shell command to sort out shell issues. It should work on a Mac but YMMV. I used to support people who used Macs and loved tcsh so I know Macs can have idiosyncrasies. But it’s doable. Maybe try this GUI approach.

Terminal.app -> Preferences -> General -> Shells open with: -> Command -> /bin/bash

Or you could just edit your /etc/passwd. Just kidding. Don’t do that. That would be really unnecessary — like Apple changing the default shell.