Catalina's Bash-to-Zsh Transition: What macOS Administrators Had to Migrate
An operational account of Catalina's zsh default: which accounts changed, what stayed on Bash, and how administrators could migrate without breaking scripts.
At WWDC on June 4, 2019, Apple announced that macOS Catalina would use Zsh (Z shell) as the default login and interactive shell for newly created accounts. For macOS administrators, the important part was not the headline but the boundary: upgraded accounts were not silently rewritten, /bin/bash was not removed, and scripts kept using the interpreter selected by their shebang or caller. A safe migration therefore began with inventory, not a global search-and-replace.
The real reason: licensing, not technical preference
The specific driver behind this change is worth understanding because it’s less about Zsh being technically superior and more about a licensing constraint Apple had been living with for years. Apple had been shipping Bash version 3.2 — a version from 2007 — as the system default for over a decade, because that was the last release of Bash licensed under GPLv2. Every Bash release since has been licensed under GPLv3, whose terms Apple has consistently avoided incorporating into macOS due to provisions around patent grants and tivoization (restricting hardware from running modified versions of covered software) that conflict with Apple’s approach to its platforms. Zsh, licensed under the MIT License, carries none of those constraints, letting Apple ship current versions and update it freely going forward.
What this meant for existing scripts and workflows
Apple didn’t remove Bash from macOS entirely — /bin/bash remained present and usable, still at that same frozen 3.2 version, meaning existing scripts explicitly invoking Bash continued working unchanged. What changed was specifically the default — new Terminal windows, and newly created user accounts, would use Zsh as their interactive login shell going forward, while anyone with a strong preference for continuing to use Bash interactively could still explicitly set it as their personal shell.
The migration surfaces administrators had to separate
Zsh and Bash are similar enough that basic interactive commands transferred with little friction, but administrators still had to separate three surfaces: the account’s recorded login shell, interactive startup files, and non-interactive automation. Zsh reads a different startup-file sequence, uses its own option model, and has deliberately different globbing behavior. Moving aliases and prompts from .bash_profile or .bashrc into .zshrc was therefore a configuration migration; changing a script interpreter was a code change that required tests.
Why this was a bigger deal for developers than casual users
Casual Terminal users largely didn’t notice much difference at all, since basic command execution behaves near-identically between the two shells for simple, everyday use. Developers and system administrators with substantial existing shell customization, or scripts that made assumptions specific to Bash’s particular behavior in edge cases, were the group that actually had to do real migration work — auditing scripts for Bash-specific syntax that Zsh interprets differently, and deciding on a per-script or per-account basis whether to explicitly pin Bash or adapt to Zsh.
The lasting macOS platform outcome
The durable macOS result was a supported modern interactive shell without redefining the operating system’s script-compatibility surfaces. Zsh became the default for new accounts, while /bin/bash, /bin/sh, explicit shebangs, and existing account records continued to mean what they said. The separate Shell-category article linked below examines the ecosystem effect; this article stays focused on fleet behavior and migration boundaries.
What administrators actually had to migrate
The Catalina change applied to the default interactive login shell for newly created accounts. It did not rewrite shell scripts, change the meaning of a #!/bin/bash shebang, or silently convert existing users’ login-shell records. Apple displayed a migration notice to users still launching Bash and documented chsh -s /bin/zsh as the supported way to switch. Fleet administrators therefore had three separate inventories: the shell recorded for each account, interactive dotfiles such as .bash_profile, and automation whose interpreter was selected explicitly by a shebang or job runner.
That distinction prevented a cosmetic default change from becoming an outage. A script written for Bash can use arrays, [[ ... ]], mapfile, or other behavior that is not portable POSIX shell. Pointing such a script at Zsh merely because the login shell changed is not a migration; it is an interpreter substitution that needs tests. Conversely, an interactive alias or prompt copied mechanically from Bash may fail because Zsh uses a different startup-file order and option model.
The durable macOS operational lesson
Apple’s decision is best read as a platform-lifecycle event. The Bash shipped in macOS remained the older GPLv2-era 3.2 line, while upstream GNU Bash continued to evolve under GPLv3. Zsh gave Apple a modern interactive default under a permissive license, but /bin/bash and /bin/sh remained compatibility surfaces. Teams should therefore declare interpreters explicitly, lint portable scripts against the shell they claim to support, and keep third-party shells patched through a managed package channel rather than assuming the operating-system copy tracks upstream.
Primary references: Apple Support: use zsh as the default shell, Apple archived shell scripting guide, GNU Bash project and license information.
Related:
Sources: