76

I know shebang line like this:

#!/bin/sh

but I found out I can also use shebang line like this:

#!/usr/bin/env python3

This confuses me, can someone explain to me how Linux will process this one?

user513951
  • 12,445
  • 7
  • 65
  • 82
user1187968
  • 7,154
  • 16
  • 81
  • 152
  • 3
    Asked and answered many times before... [Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang?](https://unix.stackexchange.com/q/29608/56041). – jww Dec 08 '18 at 07:34

3 Answers3

80

env is the name of a Unix program. If you read the manual (man env) you can see that one way to use it is env COMMAND, where in your case, COMMAND is python3.

According to the manual, this will

Set each NAME to VALUE in the environment and run COMMAND.

Running env alone will show you what NAMEs and VALUEs are set:

$ env
TERM=xterm-256color
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
…

Therefore, /usr/bin/env python3 is an instruction to set the PATH (as well as all the other NAME+VALUE pairs), and then run python3, using the first directory in the PATH that contains the python3 executable.

user513951
  • 12,445
  • 7
  • 65
  • 82
  • 1
    Do the variables persist in the local shell after `python` has quit? Or are they only local to python? – Pacerier Aug 15 '17 at 23:12
  • 1
    @Pacerier The name/value pairs in `env` originated in the shell to begin with; so yes, they persist in the shell. – user513951 Aug 16 '17 at 00:12
  • So why not have `#!/usr/bin/python3` as the shebang line? Isn't Python 3 always going to be installed here? – Al Sweigart Feb 09 '23 at 23:12
  • 2
    @AlSweigart Not everyone's executables are installed in the same place. For python this could be especially true when using virtual environments. The `env` trick is meant to increase portability between environments. There are some very good answers to your exact question here: https://unix.stackexchange.com/questions/29608/why-is-it-better-to-use-usr-bin-env-name-instead-of-path-to-name-as-my – user513951 Feb 10 '23 at 15:07
8

Newer *nix versions will resolve this the same way as the command which works.

It looks in all directories which are set in the environmental variable $PATH, whereever it is set (global, in your .bashrc or other logon script or by hand), one by one and returns the first match.

Important is, that some linux versions create alias files (aka symlinks), e.g. debian.

Another note: the bash command alias overrides this behavior as it is performed first.

Marcel Nolte
  • 116
  • 1
  • 4
-7

Essentially like

tail -n +1 yourfile | /usr/bin/env python
Hagen von Eitzen
  • 2,109
  • 21
  • 25
  • Really not the same at all. The shebang passes the source file's name as an argument, so Python knows where it is, can set `__file__`, gets a seekable handle and can reread/reload the file, etc; a pipe can only be read _once_ front-to-back and doesn't convey information about where the original file lives on disk. – Charles Duffy Jul 02 '23 at 00:41