Zsh For Macos
macOS 10.15 Catalina brought many big changes to the Mac, like lack of support for legacy 32-bit apps, but one that you could easily have missed is the default Terminal shell switching from bash (the Bourne-again shell) to zsh (Z shell). It’s an easy change to miss if you don’t use the Terminal, but also because if you upgraded from an older version of macOS, bash remains the default (though you’re prompted to switch).
Jul 22, 2019 The default shell on macOS Catalina has changed from Bash to Zsh. You have to run a command to actually make the change and many think that Zsh is better. If you’ve made the switch and want to change back to Bash as the default shell whenever you open Terminal, it’s an easy change to make. Here’s how you can switch back to bash in Terminal. With macOS Catalina arriving on my new laptop, I needed to setup my history settings again. I used to do this in bash, but now Apple has made the Zsh the default shell. A few things have changed.
If you’re a Terminal user, you need to be aware of the change, and if you’re merely Terminal-curious, now is a great time to dive in and learn more about the shell, since so many Mac-friendly user guides are being published. In our last reader survey, Terminal coverage wasn’t high on the list of desired topics (“TidBITS 2019 Reader Survey Results,” 6 September 2019), so I won’t dedicate a ton of space to zsh here but will instead point you to resources to help learn more about it.
What is a “shell?”
In the simplest terms, the shell is the command-line environment you use to interact with the operating system. Apple intends users to interact with macOS primarily through its graphical interface, but because macOS is built on top of Unix, it also offers a robust command-line environment.
Don’t confuse a shell like zsh with the Terminal app itself. Terminal loads zsh or another shell of your choice and acts as your graphical interface to the shell, which in turn is the text-based interface to macOS’s Unix foundation.
From the command line, you can execute Unix commands like cd
and ls
. A shell used in this way is referred to as an “interactive shell.” You can also string shell commands together with flow control and the like to write shell scripts that automate actions. Those can in turn also be integrated into other automation tools like AppleScript and Keyboard Maestro. In such scripts, you call the shell, usually sh
, with a starting line like #!/bin/sh
. When you use a shell like this, it’s called a non-interactive shell.
What is bash, and why did Apple switch to zsh?
Over the years, programmers have developed numerous shells with different features. Since Mac OS X 10.3 Panther, the Mac’s default shell has been the Bourne-again shell, or bash. It’s also often the default on many Linux distributions, making it something of a de facto standard. Its name is a play on the nigh-ubiquitous Bourne shell (and its many clones, like ash), often referred to by its command, sh
. The Bourne shell dates back to 1976, and while it isn’t generally used interactively, it’s still the basis for most Unix shell scripts because of its ubiquitousness. In 1989, bash emerged from the GNU Project as a newer, more modern version of sh.
There’s nothing wrong with bash, but after version 3.2, released in 2007, the GNU Project relicensed it under the GNU Public License 3.0, which places restrictions on companies like Apple, such as refraining from patent lawsuits and letting people tinker with their computers. Long story short, the 3.2.57 version of bash that ships with macOS is long out of date because Apple refuses to accept GNU’s terms. However, GNU has released small updates over the years to address things like the Shellshock vulnerability—see “Apple Updates Bash for the Shellshock Vulnerability” (29 September 2014).
In contrast, zsh is licensed under a variant of the less-restrictive MIT license. It also offers some advanced features that bash doesn’t.
What does zsh do that bash doesn’t?
The How-To Geek has a brief overview of zsh’s advantages, like automatic cd
, where you can simply type a directory name to navigate to it, and built-in spell-check. zsh also supports plug-ins, which enables things like the popular Oh My Zsh, which adds even more features and makes advanced configuration easier. I also recommend perusing the zsh FAQ, which answers various and sundry questions.
One of my favorite features of zsh is menu autocomplete. In most shells, you can start to type a command or directory name, like /usr/bi
, and then press Tab to autocomplete. In most shells, if there’s more than one autocomplete option, the shell will list the options, but you have to keep typing out the correct path by hand until there’s only one option left, after which you can press Tab to fill it in. With zsh, you can instead configure it to show your options as a menu that you can navigate and select with arrow keys, or with a bit more configuration, vi keybindings or any keys you want. In the screenshot below, I entered /usr/local/
and hit Tab to see a menu of subfolders.
How do I know which shell I’m using?
Open Terminal and enter one of these commands:
echo $0
— which shows the name of the shell.echo $SHELL
— which shows the path to the shell.
The latter command can be especially helpful if you use something like Homebrew to install different shell versions, which exist alongside those Apple ships, just in a different directory (more on that later).
Where can I learn more about zsh?
One of the best free resources for zsh in macOS is Armin Briegel’s Moving to zsh eight-part blog series. Briegel has also released a $9.99 ebook called—you guessed it—Moving to zsh—in Apple’s Book Store. If you’re serious about learning zsh in Catalina, I think it’s a good investment, as it covers in detail everything from explaining what a shell is, transitioning to zsh, and configuring zsh. It will take you from beginner to advanced user quickly, but it isn’t an exhaustive reference. For that, check out the official zsh manual.
The zsh team also offers an official user-friendly guide to zsh, which isn’t as user-friendly or Mac-focused as Briegel’s but has more raw information.
How do I customize zsh?
Out of the box, zsh is a bit spartan. I recommend Briegel’s Moving to zsh, part 2: Configuration Files for a thorough explanation of zsh’s configuration files, though you’ll have to read the rest of the series for configuration tips.
Hold off on installing a plug-in system like the aforementioned Oh My Zsh until you have a good grasp on how zsh works and what you need from Oh My Zsh. No need to make things overly complicated from the start.
Can you share your zsh configuration?
I just copy Luke Smith’s zshrc file into ~/.zshrc
. He has set up some nice colors and menu autocomplete with vi keybindings. Here’s a video explaining his configuration in detail.
If you don’t like the vi keybindings and want to use the arrow keys to navigate the menu, simply remove or comment out the five lines under # Use vim keys in tab complete menu:
.
Will my old shell scripts break?
If you started your shell scripts with the standard #!/bin/sh
, you shouldn’t have problems. Catalina still ships with bash, which emulates sh. However, I wouldn’t be surprised if Apple were to remove bash entirely in the future. Apple suggests having zsh emulate sh by adding the --emulate sh
option to zsh, so you can start a script with #!/bin/zsh --emulate sh
. (Note that this won’t work with the version of zsh that ships with Mojave.) I also refer you to Briegel’s Moving to zsh, part 8, which covers scripting with zsh.
My default shell is still bash. How do I switch to zsh?
Although zsh was not the default in older versions of macOS, nor is it the default in Catalina for older accounts which were created with bash as their default shell, Apple has long included zsh with macOS. You can give it a whirl right now by typing zsh
at the command line. Type exit
to leave zsh. If you want to set it as your default shell, Apple offers a couple of ways to do so, as well as a way to change what Terminal uses without changing the default for your account.
I don’t like zsh. Can I go back to bash? Preferably a newer version?
Yes, and it’s easy to do so. Just follow the link to Apple’s how-to page above and replace /bin/zsh
in the instructions with /bin/bash
.
However, you may not want to remain on Apple’s ancient version of bash. That’s where Homebrew comes in handy. Once you install it, running brew install bash
will update the latest version from Homebrew, which will be installed in /usr/local/bin/bash
. Note that you’ll have Apple’s version in /bin/bash
and Homebrew’s version in /usr/local/bin/bash
. If you need a feature from the newer version of bash that Homebrew installs, be sure to start your scripts with #!/usr/local/bin/bash
.
If you don’t or can’t use Homebrew, Briegel has instructions on how to build and install bash manually.
Are there alternatives to bash and zsh?
There are an absurd number of shells out there, but bash and zsh are the most common and the most worth your time to learn. However, Brett Terpstra has been documenting his experiments with the fish shell:
Fish features advanced autosuggestion and expansions, does cool syntax highlighting, offers a “sane” scripting toolset, has an array of existing plugins and themes, and even sports a browser-based configuration tool that’s pretty awesome.
I haven’t tried it, but it may be your cup of tea, er, barrel of fish.
The shell path for a user in macOS is a set of paths in the filing system whereby the user has permissions to use certain applications, commands and programs without the need to specify the full path to that command or program in the Terminal.
So instead of running something like this, with a path to the command:
You can just type the command, regardless of where you are in the filing system:
Your shell path is a bunch of absolute paths of the filing system separated by colons :
You can find out whats in your path by launching Terminal in Applications/Utilities and entering:
And the result should be like this…
So this is stating that you can run Unix style applications or commands located in 5 default locations of a certain path in the filing system:
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin
These directories are not visible by default in the filing system but you can make them visible.
Adding a Temporary Location
You can add extra locations to your path, in the mysql example above it’s location /usr/local/mysql/bin which is not in the default path, you can add it in Terminal like so:
So here I have copied my existing path and added the new location on the end, colon separate the paths. Test it by running echo $PATH again in the Terminal.
One of the disadvantages of this is that the new location will only be honored for that particular Terminal session, when a new Terminal window is launched it will have the original default path again.
Adding in a Permanent Location
To make the new pathstick permanently you need to create a .zsh file in your home directory and set the path there. This file control various Terminal environment preferences including the path.
In macOS Catalina the default shell is Zsh (previously it was the Bash Shell).
Move into home directory
Create the .zsh file with a command line editor called nano
Add in the above line which declares the new location /usr/local/mysql/bin as well as the original path declared as $PATH.
Save the file in nano by clicking ‘control’ +’o’ and confirming the name of the file is .zsh by hitting return. And the ‘control’+’x’ to exit nano – also for zsh shell remove any surrounding quotes.
So now when the Terminal is relaunched or a new window made and you check the the path by
You will get the new path at the front followed by the default path locations, all the time
Rearranging the default $PATH
If you needed to rearrange the paths in the default $PATH variable, you can just do that and leave off $PATH.
So lets say you want /use/local/bin at the beginning to take precedence you can add the default path like so inside .zsh
And then you can slot in other paths as required.