416

if I write,

#!/bin/bash
echo "foo"

or

#!/bin/sh
echo "foo"

both yields same. I have seen some scripts starting with #!/bin/sh or #!/bin/bash. Is there any difference between them?

0

4 Answers 4

358

bash and sh are two different shells. Basically bash is sh, with more features and better syntax. Most commands work the same, but they are different.

Having said that, you should realize /bin/sh on most systems will be a symbolic link and will not invoke sh. In Ubuntu /bin/sh used to link to bash, typical behavior on Linux distributions, but now has changed to linking to another shell called dash. I would use bash, as that is pretty much the standard (or at least most common, from my experience). In fact, problems arise when a bash script will use #!/bin/sh because the script-maker assumes the link is to bash when it doesn't have to be.

For more info:

7
  • 46
    Your first paragraph is quite misleading. "sh" is not a shell at all, but a symlink to the currently configured system shell, which on Linux systems is usually either bash or dash (recent versions of Ubuntu using the latter). Sep 5, 2012 at 1:16
  • 32
    /bin/sh used to be a shell called bourne shell back in 1977. bash is a /bin/sh compatible shell that can be used as a bourne shell replacement that is posix conforming. en.wikipedia.org/wiki/Bourne_shell Sep 18, 2014 at 6:57
  • 9
    bash is a de facto standard (very widely used) but it is not "standard"; sh on Ubuntu uses dash, which is a Posix-compliant shell, so it is really standard. My advice is to use dash as often as possible for scripting, especially for server-side scripts. Although bash is more expressive, dash runs quite a lot faster and is more secure.
    – Rick-777
    Sep 29, 2014 at 17:19
  • @Rick-777 So should I explicitly put #!/bin/dash at the top of my scripts? I have also written scripts where I only write commands and execute with ./scriptName and that has worked fine. Is the #!/bin/yourShellHere necessary?
    – user137717
    Aug 27, 2015 at 20:42
  • @Rick-777 In the cases where I exclude any #!/bin/shellName, I have named the files fileName.sh. Will that implicitly link to the preferred system shell without declaring #!/bin/sh?
    – user137717
    Aug 27, 2015 at 20:44
116

On Linux and other Unix-like systems you have a choice of multiple shells.

The shell is responsible not only for presenting an interactive environment where it shows a prompt, but it also interprets your commands whether they are typed or loaded from a script.

bash is the most common shell used as a default shell for users of Linux systems. It is a spiritual descendent of other shells used throughout Unix history. Its name, bash is an abbreviation of Bourne-Again Shell, an homage to the Bourne shell it was designed to replace, though it also incorporates features from the C Shell and the Korn Shell.

It's run, these days, from /bin/bash - any system with bash will have it accessible here.

Shells aren't only used interactively by users, though. Scripts (shell scripts) also need shells to interpret them. When you run a shell script, your system needs to start up a shell process to execute the script.

The problem is, different shells have small inconsistencies between them, and when it comes to running scripts, these can be a real problem. bash has quite a lot of scripting features that are unique only to bash, and not to other shells. This is fine, if you're always going to use bash to run those scripts. Other shells may try to either emulate bash, or adhere to the POSIX standard, which bash supports pretty well (though adds its own extensions to).

It's possible to specify at the top of a shell script which shell it should be run with using a shebang. A script may specify #!/bin/bash on the first line, meaning that the script should always be run with bash, rather than another shell.

/bin/sh is an executable representing the system shell. Actually, it is usually implemented as a symbolic link pointing to the executable for whichever shell is the system shell. The system shell is kind of the default shell that system scripts should use. In Linux distributions, for a long time this was usually a symbolic link to bash, so much so that it became somewhat of a convention for Linux to always link /bin/sh to bash. Bash can detect when it has been launched a "sh" symbolic link and it enables a compatibility mode allowing it to act more like older shells (primarily the Bourne shell it was designed to replace, but it also makes it more POSIX compatible). Even in this compatibility mode however, bash does provide a number of optional features that weren't available in the original Bourne shell or the POSIX standard.

In the last couple of years, Debian (and Ubuntu) decided to switch the system shell from bash to dash - breaking with a long tradition in Linux (well, GNU) of using bash for /bin/sh. Dash is seen as a lighter, and much faster, shell which can be beneficial to boot speed (and other things that require a lot of shell scripts, like package installation scripts).

Dash is fairly well compatible with bash, being based on the same POSIX standard. However, it does not implement many of the non-standard extensions that bash provided. There are scripts in existence that use #!/bin/sh (the system shell) as their shebang, but which require bash-specific extensions. This is currently considered a bug that should be fixed by Debian and Ubuntu, who require /bin/sh to be able to work when pointed to dash.

Even though Ubuntu's system shell is pointing to dash, your login shell as a user continues to be bash for now. That is, when you log in to a terminal emulator anywhere in Linux, your login shell will be bash. Speed of operation is not so much a problem when the shell is used interactively, and users are familiar with bash (and may have bash-specific customisations in their home directory).

What you should use when writing scripts

If your script requires features only supported by bash, use #!/bin/bash.

But if at all possible, it would be good to make sure your script is POSIX-compatible, and use #!/bin/sh, which should always, quite reliably, point to the preferred POSIX-compatible system shell in any installation.

32

In addition to the previous answers, even if /bin/sh is a symbolic link to /bin/bash, #!/bin/sh is not totally equivalent to #!/bin/bash.

From the bash(1) man page :

"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."

For example the bash specific syntax :

 exec  > >(tee logfile.txt)

gives an error in a shell beginning with #!/bin/sh, even with the sh->bash symbolic link in place.

15

GNU Bash: #!/bin/bash; POSIX shell: #!/bin/sh.

1

You must log in to answer this question.

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