The whole Shebang

You might have noticed that many scripts begins with lines like these:

#!/bin/sh
#!/bin/bash
#!/usr/bin/env python3

But what are they and how does it work? It looks like just a comment since the lines starts with # but there is actually a bit more meaning to it.

[!NOTE] In case you don’t know; comments in scripts are lines that doesn’t get executed as part of the script. It can be used to provide context for humans reading the script.

If the first line of a scripts starts with #!, it’s called a shebang. The line specifies the absolute path of the command that should be used to interpret the script. So if you have the line #!/bin/sh it means that it is a simple shell script. Many modern Linux flavours have /bin/sh being provided by the Bash (short for “Bourne Again SHell”) shell. Bash is like a superset of Bourne shell.

There are many other shells such as zsh, tcsh and fish.

Let’s see it in action! We start by creating a file named hello.sh this:

cat > hello.sh << EOF
#!/bin/sh
echo "Hello World"
EOF

[!TIP] The funky looking << EOF denotes a Heredoc, which is simply just a way to make multiple-line input.

We can make it executable (+x) by changing the file mode bits (chmod):

chmod +x hello.sh

Now we can run the script by typing:

./hello.sh

We can also use the shebang trick to write scripts for a different interpreter. Let’s try with Python.

cat > hello.py << EOF
#!/usr/bin/python
print("Hello World")
EOF
chmod +x hello.py
./hello.py

There are two versions of Python that a incompatible (2 and 3). Because of that, we should be specific on what version our script is written for, by changing the shebang to #!/usr/bin/python3. To improve compatibility, because Python 3 executable might not exist on the path /usr/bin/python3 on all Linux flavours (like NixOS), we should be using #!/usr/bin/env python3. The env command will lookup and execute a command with the given name.

Therefore, the final version of our Python script, which should work on most distributions, will be:

cat > hello.py << EOF
#!/usr/bin/env python3
print("Hello World")
EOF
chmod +x hello.py
./hello.py

Stay tuned for more tips…