I'm looking to switch from bash to zsh but concerned about compatibility of bash scripts.
Are all bash scripts/functions compatible with zsh? Therefore, if that is true is zsh just an enhancement to bash?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityI'm looking to switch from bash to zsh but concerned about compatibility of bash scripts.
Are all bash scripts/functions compatible with zsh? Therefore, if that is true is zsh just an enhancement to bash?
If your scripts start with the line #!/bin/bash
they will still be run using bash, even if your default shell is zsh.
I've found the syntax of zsh really close to the one of bash, and I did not pay attention if there was really some incompatibilities. I switched 6 years ago from bash to zsh seamlessly.
#!/bin/bash
will be ignored if running the script file like source ./script.sh
?
#!/usr/bin/env bash
instead, especially on macOS, where the default bash is severely outdated and new versions are virtually always installed into a different path.
Jun 4, 2019 at 7:54
Zsh can run most Bourne, POSIX or ksh88 scripts if you put it in the right emulation mode (emulate sh
or emulate ksh
). It doesn't support all features of bash or ksh93. Zsh has most features of bash, but in many cases with a different syntax.
The shell you use interactively is irrelevant for any script you have. The shell that runs the scripts is the one indicated in the first line, the shebang line. For example, if the script starts with #!/bin/bash
, it will be executed by bash.
If you've customized bash, you won't be able just rename your .bashrc
to .zshrc
. Some things can be shared, for example aliases and functions, as long as you stick to the intersection between the two shells (the intersection is close to ksh88 and pdksh). Other things, such as prompt settings, completion functions and most options, will need to be completely rewritten.
If you're writing a snippet for people to source from their .bashrc
or .zshrc
and you don't want to maintain two versions, stick to a common subset of bash and zsh features, which includes most of bash's programming features. Put your whole code in functions, and put the following line at the top of each function:
if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi
You can use emulate sh
instead of emulate ksh
to be closer to plain sh syntax, which is what you need for .profile
.
If a function calls another function, the other function inherits the emulate setting, so you don't need to put this line in internal functions, only in functions called by the end-user.
./my_script.sh
. source my_script.sh
and . my_script.sh
will run it is as the current shell, ignoring any shebang.
Aug 29, 2018 at 15:03
#!/bin/bash
from zsh, zsh calls /bin/bash
and passes the script file to it. So @BallpointBen 's comment that the shebang is ignored is misleading. Example: make a test.sh
script with #!/bin/bash
and sleep 10
in it. Then run it as ./test.sh
from zsh. Then type ps aux | grep bash
, which shows all the running processes that have bash in their names, and you will see /bin/bash ./test.sh
.
./test.sh
runs test.sh
as a separate program. Sourcing would be . ./test.sh
, so run the content of the file more or less like a function call inside the same process.
Dec 2, 2020 at 17:42
If the shebang is #!/bin/bash
and you start the script as ./script
the script will be executed by bash. Absolutely no problem here.
However, if you execute zsh ./script
or source it . ./script
to the running zsh instance, it is quite common that the syntax of bash and zsh won't match.
For example, zsh doesn't split parameter expansions by default, bash has a help builtin, there is no read -p prompt
in zsh (the syntax is very different read cmd\?prompt, arrays start on 1 (not 0) in zsh,
commandonly search for external commands in zsh, or there is no (simple) equivalent to
${foo^}` (uppercase only first character) in zsh, among others. This is a long list of (mostly) similarities and some differences.
In some cases, zsh may be told to emulate other shells. In some cases, there is no common syntax portable to both shells possible (without using aliases or functions to emulate portable solutions).
However, zsh has many (a lot) of extensions that make easier to work interactively. That is at the same time an excellent reason to switch and a problem:
ls *(.)
(which is difficult with other shells). Even if when looking deeply enough the answer becomes also complex in zsh (print -rl -- *(/)
).Con zsh:
In the end, it is your choice, and, I always like more choices.
No zsh has some differences with bash. Therefore, if you never write scripts, like you just do things from the command line, it is likely worth using zsh over bash because it has some really nice features and many utilities related to autocompletion support it.
HOWEVER, if you write scripts, you probably want to avoid having to learn 2 scripting languages so just stick with bash since it is nowadays ubiquitous, and you don't want to have to install zsh everywhere you go.
Bash and Zsh are two different interpreters with their own specifics in language syntax.
If you need Bash compatibility for debugging interactively you can always use both. Set Bash default and run exec zsh
to Z Shell and then exec bash
back to Bash.
Simply reverse if you wish Zsh to be your default shell.
echo $SHELL
when in doubt about default shell and echo $0
if in doubt of currently instanced shell.bash ./script
from zsh spawns a bash subshell for the script which may or may not be desirable.