26

I see two types of code being used:

#!/usr/bin/sh

and:

#!/user/bin/bash

I searched for this online and opinions vary a lot. The explanations I saw on most websites say that sh is older than bash, and that there is no real difference.

Does someone know the difference between these? Can you give me a practical example when to use one over the other?

2

5 Answers 5

33

bash is a superset of sh ie. everything you can do in sh you can do in bash.

Bash has more features (branching, builtins, arrays) making script easier to write. Some later *nix'es have /bin/sh as a link to /bin/bash

For a full explanation of what here's a tutorial

14
  • 5
    @Saif Bechan: One reason that the Bourne shell (sh) was not just extended is that Bash` was written by someone else. Also I bet there were license issues. Read the article about the Bourne Shell en.wikipedia.org/wiki/Bourne_shell
    – Felix
    Mar 30, 2010 at 16:32
  • 7
    Removing sh would break a lot of scripts which expect it to be there and rely on the way it parses things. Linux users might not care, but people spending $$thousands on Solaris, AIX or HP-UX might be very annoyed.
    – njd
    Mar 30, 2010 at 16:45
  • 3
    ...and for even more fun, Ubuntu symlinks /bin/sh to dash. Dash isn't completely sh or bash compliant, but is supposed to start up faster. When the system is booting, all the init.d scripts run and I guess the time saved overall is worth it.
    – kbyrd
    Mar 30, 2010 at 17:13
  • 8
    I'm pretty sure Dash is completely sh compliant. The problem is that some people write scripts that say /bin/sh, but the script itself requires /bin/bash to work. Nobody notices a problem, because most of the time, /bin/sh simply points at /bin/bash.
    – davr
    Mar 31, 2010 at 22:53
  • 8
    @Saif: There is another reason why sh was not simply extended: Its source code is pure hell. Take a look. It's supposed to be C... Mar 21, 2011 at 9:20
6

Traditionally, /bin/sh would have been the original Bourne shell, which has no history or command-line editing, and no job control.

For about the last 15 years or so, most Unixes have had the POSIX shell installed, or at least ksh or bash (which are very nearly POSIX-like), but still have the more limited shell in /bin/sh

The reason for that is so that older shell scripts which expect the older sh command will still work.
Since characters like {, } and ! have special meaning to bash, it's possible that an older shell script using those characters (without escaping them) could fail.
(The Bourne shell would take !!{1,2} literally, whereas bash would interpret that as a repeat of the previous command (!!) followed by a brace-expansion).

On Linux though, the sh command is almost always just a link to bash, with all the same features.

1
  • 2
    Bash is supposed to (but doesn't always) behave in sh-compatibility mode if invoked as /bin/sh. A lot of stuff broke when Ubuntu switched /bin/sh from linking to /bin/bash to linking to /bin/dash. The stuff that broke assumed bashisms when they should have been using standard sh.
    – Broam
    Mar 31, 2010 at 22:07
4

sh can either mean Bourne shell or /bin/sh, which is some other (POSIX-conformant) shell on most modern platforms. "The POSIX shell" is the abstract shell defined by POSIX, which is implemented by bash in POSIX mode, or ksh or dash by default. /bin/sh is sometimes also called the POSIX shell, because it's a shell that conforms to POSIX on most platforms. The original Bourne shells aren't POSIX shells.

bashref has a list of differences between bash and Bourne shells. man bash has a list of changes when bash is invoked in POSIX mode.

/bin/sh is not a symlink or hard link on OS X, but it's almost the same size as /bin/bash:

$ ls -li /bin/{ba,}sh
29631757 -r-xr-xr-x  1 root  wheel  1333920 Jul 26 01:52 /bin/bash
29631758 -r-xr-xr-x  1 root  wheel  1334000 Jul 26 01:52 /bin/sh

man bash:

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

The mimicking of Bourne shells is otherwise pretty limited. bash +B (Bourne) would actually disable features like brace expansion.

$ sh
$ echo {a,b}
a b
$ echo $BASH_VERSION
3.2.48(1)-release
$ bash +B
$ echo {a,b}
{a,b}

But even if you disable POSIX mode, echo behaves like echo -e by default:

$ sh
$ shopt -uo posix
$ echo '1\b2'
2

/bin/sh is dash on Ubuntu, so some bashisms work with /bin/sh on OS X but not Ubuntu.

If you actually want to write scripts for (something like) the original Bourne shells, you could use #!/usr/bin/env bash +B instead.

I think it's easier to write scripts for bash than to avoid features that aren't part of the POSIX specifications or Bourne shells or test everything with other shells.

2

Actually, even though /bin/sh may be a link to /bin/bash, if started up as sh it behaves differently. From the bash manpage:

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

So as sh, it tries to emulate historical sh behavior. As bash, it tries to be as useful as possible as an interactive login shell.

2

On many systems and on Solaris in particular, bash is dynamically linked while sh is statically linked. This may pose a security threat, for this reason root user should only use /bin/sh as shell (if you ever need to log as root).

1
  • 2
    Also may be useful in an emergency if you did something bad with ldconfig or your /lib directory is wiped out for some reason.
    – LawrenceC
    Mar 6, 2012 at 17:56

You must log in to answer this question.

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