What is #!

#! is called shebang when it’s at the beginning of first line of a file. When a text file with a shebang is executed, the program loader parses the rest of the file’s first line as an interpreter directive. The loader executes the specified interpreter program, passing to it as an argument the path that was initially used when attempting to run the script, so that the program may use the file as input data. For example, if a script is named with the path path/to/script, and it starts with the following line, #! /bin/sh, then the program loader is instructed to run the program /bin/sh, passing path/to/script as the first argument.

Syntax

#! interpreter [optional-arg]

in which interpreter is generally an absolute path to an executable program. The optional argument is a string representing a single argument. White space after #! is optional.

Examples

The shebang lines which I have encountered:

  • #! /bin/sh – Execute the file using the Bourne shell, or a compatible shell, assumed to be in the /bin directory.
  • #! /usr/bin/env sh – Execute with the Bourne shell, using the env program search path to find it. Check the difference of the two ways at here.
  • #! /usr/bin/env node – Execute with a Node interpreter, using the env program search path to find it.
  • #! /usr/bin/expect -f – Execute with the expect program which automates interactions with programs that expose a text terminal interface.

Purpose

Interpreter directives allow scripts and data files to be used as commands, hiding the details of their implementation from users and other programs, by removing the need to prefix scripts with their interpreter on the command line.

Portability

Program location

Shebangs must specify absolute paths (or paths relative to current working directory) to system executables. This problem can be mitigated by /usr/bin/env at most operating system.

can only pass one argument

Some systems, including Linux, do not split up the arguments; for example, when running the script with the first line like,

#! /usr/bin/env python3 -c
Copy the code

all text after the first space is treated as a single argument, that is, python3 -c will be passed as one argument to /usr/bin/env, rather than two arguments.