Solutions to common problems running Perl scripts on Unix systems.
Unix systems read the first line of files to run, and look for something to execute the subsequent data with. If this line is broken due to invisible characters, an invalid path, or text format problems, the script will not run. Note that the error below mentions the filename being run, not the typo of the bin directory name.
$ ls -l broken
-rwxrwxr-x 1 jmates jmates 40 15 Oct 11:12 broken
$ cat broken
#!/usr/bni/perl -l
print "Hello World";
$ ./broken
zsh: no such file or directory: ./broken
To check the interpreter path, copy and paste the path to see if the file can be found.
$ head -1 broken
#!/usr/bni/perl -l
$ file /usr/bni/perl
/usr/bni/perl: Can't stat `/usr/bni/perl' (No such file or directory)
Also check for invisible characters in the text file. Invisible characters could be added by accident, or if the file uses a format Unix cannot read: legacy Macintosh \r or Internet linefeeds \r\n may cause problems on Unix, which expects \n.
The head and od commands reveal invisible characters. The following example, for macos.pl, contains Macintosh \r line breaks.
$ head -1 macos.pl | od -c
0000000 # ! / u s r / b i n / p e r l
0000020 - w l \r p r i n t " H e l l o
0000040 W o r l d " ; \r
0000051
$ cat -v macos.pl
#!/usr/bin/perl -wl^Mprint "Hello World";^M
Tools like dos2unix or BBEdit can convert line breaks between different formats used by Unix, Windows, and legacy Mac OS applications. Unix requires \n linebreaks.
$ perl -i -ple 's/\r/\n/g' macos.pl
$ perl -i -ple 's/\r//g' dos.pl
A trick on Unix systems to run perl code relies on the Unix convention to run the shell (usually /bin/sh) if no other interpreter can be found. Note the single quotes around EOF, which disable shell variable interpolation inside the subsequent heredoc.
exec perl <<'EOF'
print "Hello World\n";
I do not consider #!/usr/bin/env perl a better way to find perl than #!/usr/bin/perl and other direct invocations, just another sometimes useful, sometimes flawed method. /usr/bin/env is both optimistic and lazy, a hope that some perl exists, somewhere, without confirmation that the perl found is actually suitable for the script in question. Optimistic, as it hopes a correct version of perl (and related libraries and modules) always appears first in the PATH environment variable, and that no user who will ever run the script on any system will ever have a incompatible version of perl installed (or again related libraries and modules), or that the user has not tweaked their PATH to list an incorrect version of perl first, or whether env works at all (it did not on Mac OS X 10.2). Lazy, as due diligence ensuring that a perl with the proper libraries and modules and configuration is available in a consistent and reproducible manner has perhaps not been performed: and how would one know, when a random perl is being pulled out of PATH? Any user need only, at any time, to change their PATH slightly, or install a custom perl somewhere, and the script will at best fail noisily, or at worst silently use some different module version to generate data incompatible with other invocations of the script, to who knows what ill effect.
I simply set #!/usr/bin/perl, as this suits the systems I currently administer, and would use configuration management to adjust the shebang as appropriate or a software depot (see below) if a different site required a different approach. I would not throw caution to the wind, and hope that the vendor env finds something, as this strikes me as a great way to create hard to debug problems.
Software depot—see The Practice of System and Network Administration for a thorough discussion of these—organize sets of known versions of software into unique environments, where a depot version of env—most definitely not the vendor /usr/bin/env—can determine the proper path, LD_LIBRARY_PATH, @INC, and so forth. This allows multiple versions of perl and other software, with versions appropriate to the script, to exist on the same system, with lessened risk that the wrong environment and therefore wrong perl would be used to run the wrong script. A user could still manually run script A from environment A with perl B from environment B, but that would be a manual action. The custom software depot env wrapper, without any deliberate misdirection by the user, would only run script A with perl A under environment A, or fail if unsure as to what environment must be used.
Trying to run Perl on a Windows system? Good luck!