Home » What is the difference between #!/bin/sh and #!/bin/bash?

What is the difference between #!/bin/sh and #!/bin/bash?


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, http://man.cx/sh, http://man.cx/bash.

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

The shell is responsible not only for drawing your little prompt, but interpreting your commands, especially if you put in complicated logic like pipes, conditionals and so on.

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.

It’s not just users that use shells, though. Scripts (shell scripts) need shells to interpret them. When you run a shell script, your system needs to start up a shell process to execute your script.

The problem is, different shells have tiny little 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 has become somewhat of a convention to always link /bin/sh to bash or a bash-compatible shell. However, in the last couple of years Debian (and Ubuntu) decided to switch the system shell from bash to dash – a similar shell – 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 doesn’t implement the bash-specific extensions. 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 at this time. 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.

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.

Related Solutions

Why would anyone choose not to use the lowlatency kernel?

The different configurations, “generic”, “lowlatency” (as configured in Ubuntu), and RT (“real-time”), are all about balancing throughput versus latency. Generic kernels favour throughput over latency, the others favour latency over throughput. Thus users who...

How can I update all Snap packages?

sudo snap refresh Will do this. It is part of snapd 2.0.8, which landed 2016-06-13 in xenial-updates. snap refresh --list Only lists the updates without refreshing the packages. snap info <snap name> Can show which versions are available for a particular...

What does Controls.Add() do in c#? [closed]

Controls is an instance of Control.ControlCollection class, which represents a collection of Control objects, Inheritance hierarchy is System.Windows.Forms.Control.ControlCollection Note: The Add, Remove, and RemoveAt methods enable you to add and remove...

How can I change the date modified/created of a file?

As long as you are the owner of the file (or root), you can change the modification time of a file using the touch command: touch filename By default this will set the file's modification time to the current time, but there are a number of flags, such as the -d...

How to read dmesg from previous session? (dmesg.0)

Although a bit late for the OP... I use Fedora, but if your system uses journalctl then you can easily get the kernel messages (dmesg log) from prior shutdown/crash (in a dmesg -T format) through the following. Options: -k (dmesg) -b < boot_number > (How...

Get data on daily basis in laravel

You can use the existing Laravel cron job scheduling to fulfill your specific requirement. Please refer following Laravels official documentation https://laravel.com/docs/5.8/scheduling#scheduling-queued-jobs I'll show a simple example to get an idea about this...

Python speed testing – Time Difference – milliseconds

datetime.timedelta is just the difference between two datetimes ... so it's like a period of time, in days / seconds / microseconds >>> import datetime >>> a = datetime.datetime.now() >>> b = datetime.datetime.now() >>> c = b...

Discovering metadata about a PDF

One of the canonical tools for this is pdfinfo, which comes with xpdf, if I recall. Example output: [0 1017 17:10:17] ~/temp % pdfinfo test.pdf Creator: TeX Producer: pdfTeX-1.40.14 CreationDate: Sun May 18 09:53:06 2014 ModDate: Sun May 18 09:53:06 2014...

How can I search within the output buffer of a tmux shell?

copy mode search To search in the tmux history buffer for the current window, press Ctrl-b [ to enter copy mode. If you're using emacs key bindings (the default), press Ctrl-s then type the string to search for and press Enter. Press n to search for the same...

Often big numbers become negative

This image shows what you're looking for. In your case it's obviously larger numbers, but the principle stays the same. Examples of limits in java are: int: −2,147,483,648 to 2,147,483,647. long: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 In the...

null pointer exception in java servlet [closed]

I got a "null pointer exception" fault in java servlet. Could someone tell me what happens? And how to avoid that? That happens when you're trying to access/invoke some reference which is actually null. SomeObject someObject = null; someObject.doSomething(); //...

How to set ulimits on service with systemd?

The mappings of systemd limits to ulimit Directive ulimit equivalent Unit LimitCPU= ulimit -t Seconds LimitFSIZE= ulimit -f Bytes LimitDATA= ulimit -d Bytes LimitSTACK= ulimit -s Bytes LimitCORE= ulimit -c Bytes LimitRSS= ulimit -m Bytes LimitNOFILE= ulimit -n...

Does compression option -z with rsync speed up backup

It's a general question. Does compression and decompression at endpoints improve the effective bandwidth of a link? The effective (perceived) bandwith of a link doing compression and decompression at endpoints is a function of: how fast you can compress (your...

How to pre-download items from a JSON list array in React JS?

You can insert <link rel="prefetch"> elements into the <head> of the page. This will tell the browser to go ahead and download the thing that it finds in the src property of that element so that it can be served from the cache if something else on...

C programming: Use of undeclared identifier [closed]

There are a lot of error in this program. In c programming, before using a variable, we must explicitly declare the type of data that it can store. So you must define the type of x and y to integer type (int x = 10,int y=12). The next thing is that you are...