Skip to main content
Explain

What is Shebang in Linux Shell Scripting?

The seemingly insignificant #! characters at the beginning of a shell script has a major significance on how your script will be executed.

Abhishek Prakash

Warp Terminal

You'll often come across shell scripts that start with:

#!/bin/bash

This #! is called shebang or hashbang. The shebang plays an important role in shell scripting, specially while dealing with different types of shell.

In this tutorial, you'll learn:

  • What is Shebang?
  • How does it play an important role in shell scripting?

What is shebang in shell scripting?

The shebang is the combination of the # (pound key) and ! (exclamation mark). This character combination has a special meaning when it is used in the very first line of the script. It is used to specify the interpreter with which the given script will be run by default.

So, if the first line of a script is:

#!/bin/bash

It means the interpreter should be bash shell. If the first line is:

#!/bin/zsh

It means the interpreter to be used is Z shell.

The #! is surely special because # is used for comments in shell scripts but here it has a special meaning.

Why the shebang matters in shell scripting?

Here's the thing. The shebang followed by the executable of the shell is not mandatory for a script.

If you write a simple script like this:

echo "Namaste, folks!"

And give it execute permission and run it with the . operator, it will be run by your login shell.

abhishek@lhb:~$ cat sample 
echo "Namaste, folks!"
abhishek@lhb:~$ chmod u+x sample 
abhishek@lhb:~$ ./sample 
Namaste, folks!
Shebang is not mandatory in shell scripts

Then why do shell scripts include #!/bin/bash line at the beginning of the script?

Because there are several shells available for Linux and UNIX systems. While these shells have mostly common syntax, they do have different syntax or different way of handling things.

This is why it becomes important to specify the correct shell interpreter in the script, otherwise some scripts may produce different results when run in different shells.

Let me show that to you with a simple example.

Importance of specifying shell interpreter with shebang

I have written a sample shell script with an array of distributions. The script then displays the distro at index 2.

distros=("Ubuntu" "Fedora" "SUSE" "Debian")
echo "Distro at index 2 is: ${distros[2]}"

I have not added the shebang line to specify any shell interpreter. This means when I execute this script, it will be run by the default shell (bash in my case):

abhishek@lhb:~$ echo $0
bash

Can you guess the output of the script?

abhishek@lhb:~$ ./arrays.sh 
Distro at index 2 is: SUSE

It shows SUSE at index 2 because array index start at 0 in Bash and many other programming and scripting languages. BUT that's not the case in Z shell. In Z shell, array index starts at 1.

I have Z shell installed on my system. I change the script and add the shebang line to specify that the script should be run by Z shell by default.

#!/bin/zsh

distros=("Ubuntu" "Fedora" "SUSE" "Debian")
echo "Distro at index 2 is: ${distros[2]}"

Can you guess the output when I run the script now?

abhishek@lhb:~$ ./arrays.sh 
Distro at index 2 is: Fedora

Do you notice the difference now? It's the same script but the addition of the shebang line made the difference.

And this is why specifying the correct shell interpreter with shebang operator is important. As a sysadmin, you might write shell scripts keeping a specific shell in mind, be it bash, ksh or zsh. But you cannot be sure that the system that will run the script will have the same default shell as yours. Now things make sense, right?

Shebang is ignored if you explicitly specify shell

Why am I stressing on "default" shell? Because the shebang specifies the interpreter to run the script with.

You may, however, specify the shell explicitly and in such cases, the shebang line will be ignored.

How exactly the shebang work?

When you use the shebang in the first line of a script, you are telling the shell to run the given script with the specified command.

Basically, #!/bin/zsh is equivalent to:

/bin/zsh script_name

I have told you that if the first line of a script starts with shebang, it means you are specifying the shell interpreter.

That's only partially true. Actually, that's the purpose of the shebang character. But it's not necessary that shebang line must have executable of a shell. It can be anything.

For example, I am going to replace #!/bin/zsh with #!/bin/cat. /bin/cat is the executable of the cat command.

#!/bin/cat

distros=("Ubuntu" "Fedora" "SUSE" "Debian")
echo "Distro at index 2 is: ${distros[2]}"

This means that now this script will run with cat command and display the content of the script.

It will work as long as it points to an executable command. If you put some random stuff, it will throw error.

I change the shebang line to:

#!/home/abhishek

Clearly, it does not point to the executable of any command and thus it throws a bad interpreter error.

abhishek@lhb:~$ cat arrays.sh 
#!/home/abhishek

distros=("Ubuntu" "Fedora" "SUSE" "Debian")
echo "Distro at index 2 is: ${distros[2]}"
abhishek@lhb:~$ ./arrays.sh 
bash: ./arrays.sh: /home/abhishek: bad interpreter: Permission denied

Conclusion

Let me answer a few more questions before ending this article:

  • It is important that there is no space between # and !. You CANNOT use it like this: # !/bin/bash.
  • Most system allow space between #! and /bin/bash however it is a good practice to avoid space between #! and /bin/bash.
  • #! has to be on the first line, otherwise the shebang line will be treated as comment. You cannot even have a blank line before it.

I hope you have a better understand on why #! is used in the beginning of shell scripts in Linux. Feel free to leave a comment if you have questions or suggestions.

Abhishek Prakash