Digression: Interpreters

On a linux system, when a script is executed, what you are doing is to send it directly to the kernel: if a file is an executable (e.g. a program you have compiled or someone else compiled for you, like your editor) then the kernel and various user level programs take care of it, otherwise, if the file starts with the #! characters, the kernel executes the program that follows them and pass to it the file as an argument.

Therefore, a file test.sh containing this lines:

#!/bin/bash

echo 'Hello!'

will be executed like:

bash test.sh

where a python script, like this one:

#!/usr/bin/python

print "Hello!"

will be passed to the python executable.

Arguments can also be specified in the first line: a common situation is to pass the -x flag to the bash, in this way:

#!/bin/bash -x

echo 'Hello!' 

which prints on the standard error stream the trace of execution: this can be quite useful for debugging a script which is not doing what it's meant to (just try it to get an idea).

Since the interpreter in the first line should be specified with the correct path, a problem arises: what if we are moving a script from a computer to another and the position of the program that should interpret it (e.g. python) lies in another position on the filesystem (having it in /usr/local/bin is not uncommon)?

The script will not work.

For this reason, the env command exists: if put in the first line instead of the real interpreter (it's path is always the same: /usr/bin/env), with the interpreter passed as an argument, it will search the program for the kernel and let it execute the script correctly.

This:

#!/usr/bin/env python

print 'Hello!'

will run correctly on any system, as long as the python executable will be found in the PATH.