3 ms·
Rule of thumb about shells: You'll never know for sure what shell is the default, so write your scripts to a minimum shell family, and encode the name of tha
by throwaway892238 3y ago
Rule of thumb about shells:
You'll never know for sure what shell is the default, so write your scripts to a minimum shell family, and encode the name of that shell family in the shebang.
The default shell, for either the entire system or an individual user, could be:
- A Bourne shell
- A C shell
- A POSIX shell
- A "modern" shell, like Bash, Zsh, Fish, Osh
Use the following shebangs to call the class of shell you expect. Start with /usr/bin/env to allow the system to locate the executable based on the current PATH environment variable rather than a fixed filesystem path.
#!/usr/bin/env sh
# ^ should result in a Bourne-like shell, on modern systems, but could also be
# a POSIX shell (like Ash), which is not really backwards compatible
#!/usr/bin/env csh
# ^ should result in a C shell
#!/usr/bin/env bash
# ^ should result in a Bash shell, though the only version you should
# expect is version 3.2.57, the last GPLv2 version
#!/usr/bin/env dash
# ^ you expect the system to have a specific shell. if your code depends
# on Dash features, do this. otherwise write your code using an earlier
# version of the original shell family, such as Bourne or POSIX.
If you need to pass a command-line argument to the shell command before interpreting your script, use the fixed filesystem path for the shell. Due to bugs in the way kernels execute scripts, all arguments after the initial shebang path may be sent as a single argument, which is probably not what you (or the shell command) expect. (e.g. use #!/bin/bash --posix instead of #!/usr/bin/env bash --posix as the latter may fail)
Different shells have different implementation details. For example, Bash tends to skew toward POSIX conformance by default, even if it conflicts with traditional Bourne shell behavior. Dash may try to implement POSIX semantics, but also has its own specific behavior incompatible with POSIX.
In order to get specific behavior (like POSIX emulation), you may need to add a flag like --posix, or set an environment variable like POSIXLY_CORRECT. For shells that support it, you can also detect the version of the shell running, and bail if the version isn't compatible with your script.
Here are some references of the differences between shells:
- Comparison of command shells[1]
- Major differences between Bash and Bourne shell[2]
- Practical differences between Bash and Zsh[3]
- Fundamental differences between mainstream \*NIX shells[4]
[1] https://en.wikipedia.org/wiki/Comparison_of_command_shells https://en.wikipedia.org/wiki/Comparison_of_command_shells [2] https://www.gnu.org/software/bash/manual/html_node/Major-Differences-From-The-Bourne-Shell.html https://www.gnu.org/software/bash/manual/html_node/Major-Dif... [3] https://apple.stackexchange.com/questions/361870/what-are-the-practical-differences-between-bash-and-zsh/361957#361957 https://apple.stackexchange.com/questions/361870/what-are-th... [4] https://unix.stackexchange.com/questions/3320/what-are-the-fundamental-differences-between-the-mainstream-nix-shells https://unix.stackexchange.com/questions/3320/what-are-the-f...
- alwillis 3y agoJust checked; macOS comes with Dash in addition to Bourne shell (sh) and Bash.