The first line of Perl_CGI script, env perl vs perl only, how different?

Hi ! Everyone there ! How are you ?

Until recently I runs all of my Perl scripts as well as Perl_CGI scripts by starting the folowing salutation,

#! /usr/bin/perl -w

The script with this beginning runs well at BASH shell at (/home/mkido/bin) LINUX such as Fedora, Ubuntu, Rocky (Alma-derivative). However, almost right now I noticed some of Perl example around has the different first line as below,

#! /usr/bin/env perl

And it doesn't seem to run at HOME BASH shell (/home/mkido/bin) by simple way of executing it by-itself by the command line. Will someone explain me about what is this [env perl] stuff? Thank you so much.

Mitsuru Kido


The difference doesn't have anything to do with Perl; it's how unix-like operating systems interpret files that start with a shebang (#!).

The first part after the shebang is the pathname to the executable that will be called with the file as the argument. If your file starts with

then the OS will execute the /usr/bin/perl file and hand it your script... assuming there's a /usr/bin/perl file to execute (usually there is). It's the exact equivalent to typing /usr/bin/perl at your command line.

However, if your script starts with

#!/usr/bin/env perl
the OS will execute the /usr/bin/env file and hand it your script. How is this different? Well, the difference is that /usr/bin/env looks at the rest of the first line and it searches for the command in your path. Let's say you have /usr/bin/perl, but it's a crappy perl 5.10 that was installed by your operating system, and you have perl 5.36 installed at /usr/local/bin/perl. Putting /usr/local/bin in your path earlier than /usr/bin isn't going to do any good if your scripts all start with
(or if you run all your scripts from the command line with /usr/bin/perl, because those scripts will execute using the crappy 5.10 that's available at /usr/bin/perl. By using #!/usr/bin/env perl, it's the same as invoking the perl : the OS searches your path and uses the first perl executable it finds, whether that's the one you have installed at /usr/local/bin/perl, or $HOME/perl5/bin/perl, or $HOME/perl5/perlbrew/perls/perl-5.36.0/bin.

You can read more about the env command at

Also, the -w you see in the #!/usr/bin/perl -w is just passing the "enable warnings" flag to Perl. If you're using /usr/bin/env, you can do the same thing by putting

#!/usr/bin/env -S perl -w

However, I dislike using command line switches to do things in shebang lines. Command line switches are good for one-liners, but if I'm writing a script anyway, I'm just going to do things in a more verbose, easier to read way. That's why all my perl scripts start with

#!/usr/bin/env perl
use strict;
use warnings;

More info on how to invoke Perl:

Avoiding doing things on the shebang line is a matter of coding style and therefore subjective.

There is a much more important reason to avoid -w, which is objective: it’s not at all the same thing as use warnings. Whereas use warnings applies to the rest of the current scope, -w is completely global. Under -w, any module loaded directly or indirectly will have warnings forced on it, even if the module itself does not turn on warnings – which nowadays almost certainly means it was written to run without warnings. Therefore -w should no longer be used. At all.

We have had use warnings since Perl 5.6 – in fact lexical warnings were one of the major changes in that version. 5.6 came out in 2000. The -w switch is 1990s technology.

I've also seen this:


And it seems to work like "#!/usr/bin/env perl" on Linux (i.e. $PATH is consulted), but it fails completely on macOS. Best avoided.

Leave a comment

About Kido Mitsuru

user-pic To ask questions to this blog community