Since the beginning of times (Unix, i.e. January 1, 1970), it was recommended to use shebang / hashbang in the beginning of the script - a line indicating the interpreter used, for example

#!/bin/bash echo 'hello world' #!/usr/bin/python print 'hello world' #!/usr/bin/python3 print('hello world') 

Recently I came across a recommendation to use this form instead:

 #!/usr/bin/env bash echo 'hello world' #!/usr/bin/env python print 'hello world' #!/usr/bin/env python3 print('hello world') 

Please explain how it works and what are the advantages of this approach? If there are limitations and / or disadvantages compared to the usual way, then I would like to hear about them.

4 answers 4

The main idea is to improve portability. It is not guaranteed that on various systems the executable file will lie along the path that is specified in shebang.

Using env allows you to reduce this risk by running a command based on data from the PATH environment variable.

Moreover, if for some reason, instead of the standard executable file, the user wants to use his own, then it is enough to add the path to this file in the PATH without the need to fix the scripts:

 ~ $ cp /bin/bash /home/soon/python ~ $ export PATH=/home/soon:$PATH ~ $ env python [soon@archlinux ~]$ exit 

In the example above, I copied bash to my home directory (renaming the file in python), added the path to the PATH and started python with the help of env , which ushered bash , because found it before.

Another example is the use of virtual environments in Python development (virtualenv). Since they also interrupt the PATH , env allows you to use the correct version of the executable file:

 ~ $ workon black-box-challenge-2016-py2 ~ (venv:black-box-challenge-2016-py2) $ env python Python 2.7.11 (default, Mar 31 2016, 06:18:34) [GCC 5.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> print sys.executable /home/soon/.virtualenvs/black-box-challenge-2016-py2/bin/python >>> 

a brief summary of the information given in the answers to this question and similar questions:

advantages:

  • the program will be launched not from the specified file, but from the fact that it will be the first in the list of directories specified by the PATH environment variable of the user running the script.

    useful for cases where the specified path in the system on which the script will be executed does not contain such a file, or when the user modifies this environment variable in order to run some special program (another implementation, another version).

limitations:

  • the program will be launched not from the specified file, but from the fact that it will be the first in the list of directories specified by the PATH environment variable of the user running the script.

    for example, different users (or the same user, but with the modified contents of this environment variable) may get different results of executing the same script.

  • the /usr/bin/env program may not exist on the system where the script will be launched, respectively, the launch attempt will fail.
  • It will not be possible to specify additional options for the program being executed. as it happens:

     #!/путь/к/программе опция 

    and so - no:

     #!/usr/bin/env программа опция 

This is due to the portability of scripts. The fact is that the path to python , for example, on different systems may be different, but the path to env on all systems is unchanged. Therefore, by calling env and passing the necessary interpreter as an argument, you can be sure that the script will be launched regardless of where the interpreter is actually located (the main thing is that it is in the PATH ).

    The env command displays the current environment variables. And if you are with a team

     env bash 

    This executes the command with the current environment variables.

    In some systems, when running interpreters, the current environment variables are not used, but are read from files or even set by default. And if you change or add environment variables, they will not be taken into account in the launched script, and when launched via env all variables will be taken into account.

    • Wrong, not here used it. - Yaroslav