Tell me more ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I notice that some scripts which I have acquired from others have the shebang #!/path/to/NAME while others (using the same tool, NAME) have the shebang #!/usr/bin/env NAME.

Both seem to work properly. In tutorials (on Python, for example), there seems to be a suggestion that the latter shebang is better. But, I don't quite understand why this is so.

I realize that, in order to use the latter shebang, NAME must be in the PATH whereas the first shebang does not have this restriction.

Also, it appears (to me) that the first would be the better shebang, since it specifies precisely where NAME is located. So, in this case, if there are multiple versions of NAME (e.g., /usr/bin/NAME, /usr/local/bin/NAME), the first case specifies which to use.

My question is why is the first shebang preferred to the second one?

share|improve this question
2  
See this answer... – jasonwryan Jan 21 '12 at 1:10
Thanks! That's an excellent, detailed answer! – TheGeeko61 Jan 21 '12 at 2:02
@TheGeeko61: In my case I had something broken and some variables wasn't in env. So I suggest to use this shebang to verify if env is correctly loaded. – Phpdna Jan 21 '12 at 10:52

4 Answers

up vote 43 down vote accepted

It isn't necessarily better.

The advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.

The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.

That means that the script could behave differently depending on who runs it. For one user, it might use the /usr/bin/python that was installed with the OS. For another, it might use an experimental /home/phred/bin/python that doesn't quite work correctly.

And if python is only installed in /usr/local/bin, a user who doesn't have /usr/local/bin in $PATH won't even be able to run the script. (That's probably not too likely on modern systems, but it could easily happen for a more obscure interpreter.)

By specifying #!/usr/bin/python you specify exactly which interpreter will be used to run the script on a particular system.

Another potential problem is that the #!/usr/bin/env trick doesn't let you pass arguments to the intrepreter (other than the name of the script, which is passed implicitly). This usually isn't an issue, but it can be. Many Perl scripts are written with #!/usr/bin/perl -w, but use warnings; is the recommended replacement these days. Csh scripts should use #!/bin/csh -f -- but csh scripts are not recommended in the first place. But there could be other examples.

I have a number of Perl scripts in a personal source control system that I install when I set up an account on a new system. I use an installer script that modifies the #! line of each script as it installs it in my $HOME/bin. (I haven't had to use anything other than #!/usr/bin/perl lately; it goes back to times when Perl often wasn't installed by default.)

A minor point: the #!/usr/bin/env trick is arguably an abuse of the env command, which was originally intended (as the name implies) to invoke a command with an altered environment. Furthermore, some older systems (including SunOS 4, if I recall correctly) didn't have the env command in /usr/bin. Neither of these is likely to be a significant concern. env does work this way, a lot of scripts do use the #!/usr/bin/env trick, and OS providers aren't likely to do anything to break it. It might be an issue if you want your script to run on a really old system, but then you're likely to need to modify it anyway.

share|improve this answer
1  
Wow! Such a thorough discussion of all 3 sides of the coin. LOL I appreciate your answer. – TheGeeko61 Jan 21 '12 at 8:31
1  
If /usr/bin/perl is perl 5.8, $HOME/bin/perl is 5.12, and a script requiring 5.12 hardcodes /usr/bin/perl in the shebangs, it can be a major pain to run the script. I've rarely seen having /usr/bin/env perl grab perl from the PATH be a problem, but it is often very helpful. And it is much prettier than the exec hack! – William Pursell Jan 25 '12 at 20:30
@WilliamPursell: What happens when someone else who doesn't have your $HOME/bin in their $PATH tries to run the script? – Keith Thompson Jan 25 '12 at 20:59
@Keith They cannot run it, but since the script is in $HOME/bin, it's not a problem. If you have privileges to put the script in /usr/bin, then you can upgrade /usr/bin/perl (although that's probably a bad idea.) I've been on boxes where I wanted to install a fairly large package of perl scripts that hard coded /usr/bin/perl in $HOME, did not have root, and had to go through the entire package modifying the shebang. I was most unhappy. – William Pursell Jan 25 '12 at 21:55
@WilliamPursell: You could always write a Perl script to replace the shebangs for you! – Keith Thompson Jan 26 '12 at 22:04
show 1 more comment

Because /usr/bin/env can interpret your $PATH, which makes scripts more portable.

#!/usr/local/bin/python

Will only run your script if python is installed in /usr/local/bin.

#!/usr/bin/env python

Will interpret your $PATH, and find python in any directory in your $PATH.

So your script is more portable, and will work without modification on systems where python is installed as /usr/bin/python, or /usr/local/bin/python, or even custom directories (that have been added to $PATH), like /opt/local/bin/python.

Portability is the only reason using env is preferred to hard coded paths.

share|improve this answer
Thanks for a precise (and concise!) answer. I appreciate it. – TheGeeko61 Jan 21 '12 at 2:06

Adding another example here:

Using env is also useful when you want to share scripts between multiple rvm environments for example.

Running this on the cmd line, shows which ruby version will be used when #!/usr/bin/env ruby is used inside a script:

env ruby --version

Therefore, when you use env, you can use different ruby versions through rvm, without changing your scripts.

share|improve this answer
This does not address the question. This answer is indicating why one would want to run env from the command line. It is not addressing the issue of placing (or omitting) it in the shebang. – TheGeeko61 Jan 23 '12 at 0:06
This is just another example that directly answers your question. If you're using rvm (or the python equivalent) you benefit from using #!/usr/bin/env exe. The cmd line is just for illustration of the same results. – Not Now Jan 23 '12 at 0:17
Ok. My bad. I tried removing the downvote. But the system will not allow me to until the answer has been modified... – TheGeeko61 Jan 23 '12 at 0:27

Specifically for perl, using #!/usr/bin/env is a bad idea for two reasons.

First, it's not portable. On some obscure platforms env isn't in /usr/bin. Second, as someone else has noted, it can cause trouble with passing arguments on the shebang line. The maximally portable solution is this:

#!/bin/sh
exec perl -x $0 "$@"
#!perl

For details on how it works, see 'perldoc perlrun' and what it says about the -x argument.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.