What is a shebang? How scripts know which interpreter to use

If you have ever opened a shell script or a Node.js file and noticed a strange-looking first line starting with #!, you have encountered a shebang. It is a small but important detail that controls how a script is executed, and understanding it will save you confusion when writing or running scripts across different environments.


Why is it called a shebang?

The name comes from the two characters used to write it. The hash symbol (#) is sometimes called “sharp” in musical notation, and the exclamation mark (!) is commonly called “bang” in computing. Put them together and you get “sharp-bang” or “hash-bang”, which over time was shortened to “shebang”.


What does a shebang do?

When you run a script file, the operating system needs to know which program should be used to interpret it. Without any instruction, it will fall back to the default shell, which may not be appropriate for the script being run.

A shebang on the first line of a script tells the OS exactly which interpreter to use for that particular file, regardless of what the default shell or runtime is. The format is straightforward: #! followed by the path to the interpreter.

#!path_to_interpreter

When the OS encounters this line, it uses the specified interpreter to execute the rest of the file. The shebang line itself is treated as a comment by the interpreter and is not executed as code.


Shell script shebangs

For shell scripts, the shebang specifies which shell should be used to run the script. The most common examples are:

#!/bin/sh
#!/bin/bash

#!/bin/sh points to the system’s default POSIX-compatible shell, which is the most portable option. #!/bin/bash specifies Bash explicitly, and should be used when your script relies on Bash-specific features not available in other shells.

This is the solution to the Bash and Zsh compatibility problem discussed in Getting Started with the Command-Line Shell. If you use Zsh as your default shell but run a script that requires Bash, adding #!/bin/bash as the first line ensures the correct interpreter is used automatically.


Absolute path vs env

There are two commonly used conventions for writing a shebang, and it is worth understanding the difference between them.

The first is to point directly to the absolute path of the interpreter:

#!/bin/bash
#!/usr/bin/node

This is simple and explicit, but it assumes the interpreter is installed at that exact path on every machine the script runs on. This is not always a safe assumption. The location of interpreters can vary between operating systems and installations.

The more portable convention uses env:

#!/usr/bin/env bash
#!/usr/bin/env node

env is a utility that is reliably found at /usr/bin/env on virtually all Unix-like systems. Rather than pointing directly to the interpreter, you pass the interpreter name as an argument to env, which then locates it using the system’s PATH. This means the script will work correctly regardless of where Bash or Node.js is installed on a given machine.

For scripts intended to run across different environments or to be shared with others, the env convention is generally the safer choice.


Node.js shebangs

The shebang is not limited to shell scripts. Node.js scripts can use the same mechanism to make a JavaScript file directly executable from the command-line, without needing to prefix the command with node. The recommended shebang for Node.js scripts is:

#!/usr/bin/env node

This is preferred over #!/usr/bin/node for the same portability reason described above. Node.js may not be installed at /usr/bin/node on every system, but env will locate it via PATH wherever it is installed.


Further reading


Posted

in

,

by