5

Based on what I've read online, sh is essentially an alias for bash; running a shellscript with sh will behave the same as if it's run with bash.

In my experience this is not entirely true, as newlines are processed differently. What exactly is the difference between sh and bash, and as zsh is now the default shell does anyone know if sh will change in future versions of Mac OS?

Consider the following code:

sh -c "echo \"Hello\nWorld\""

This should produce the following output:

Hello
World

However when run with bash:

bash -c "echo \"Hello\nWorld\""

The newline is not output:

Hello\nWorld

Thanks in advance!

2
  • @user3439894 Under BigSur /bin/sh is just a wrapper which executes the shell /var/select/sh points to (which in my case is bash), see man sh for details.
    – nohillside
    Jan 1, 2021 at 16:04
  • It might be the same already for Catalina, run strings /bin/sh to check.
    – nohillside
    Jan 1, 2021 at 16:05

1 Answer 1

4

The long answer on this has already been written, see https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash.

The echo builtin is one (of several) things where sh and bash differ. To get bash to handle \n as a control character use echo -e.

$ bash -c "echo -e \"Hello\nWorld\""
Hello
World

As for the definition of sh on macOS, see man sh (e.g. on Big Sur):

sh is a POSIX-compliant command interpreter (shell).  It is implemented by re-execing as 
either bash(1), dash(1), or zsh(1) as determined by the symbolic link located at 
/private/var/select/sh. If /private/var/select/sh does not exist or does not point to a
valid shell, sh will use one of the supported shells.

So basically executing sh will execute whichever shell /private/var/select/sh points to in "sh/POSIX compatibility mode".

4
  • Thank you very much. That's certainly given me some clarification, but /private/var/select/sh does not seem to exist for me. sh --version outputs GNU bash, so it must be linking to bash. What I'd like is a way for my current shellscripts, without modification, to run through bash and behave as they do with sh. I've tried the --posix argument but that's not making any difference. The reason I want to do this is it sounds like the sh may be fundamentally different across machines. Maybe what I want to achieve isn't possible without modifying my scripts. Jan 1, 2021 at 16:26
  • @BenCheshire sh must behave the same for all systems adhering to POSIX/the Unix standard. So as long as you use #!/bin/sh the script should work on all Unix systems. It also doesn't matter whether /bin/sh is a binary on its own or just linked to bash, zsh etc. Running either as sh will ensure sh compatibility and turn off any shell-specific functions.
    – nohillside
    Jan 1, 2021 at 16:34
  • Interesting. That should save me a lot of bother. Thanks! Jan 1, 2021 at 16:36
  • This answer explains it quite nicely, actually.
    – nohillside
    Jan 1, 2021 at 16:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .