How to set the cross platform interpreter path? - perl

I would like my scripts works on Windows and UNIX system, so I want some code as blew(just a sample, not work)
if $^O eq 'MSWin32' {
#!/c:/perl/bin/perl.exe
}
else { / non-windows system
#!/usr/local/bin/perl
}
is there any way to do this in perl? it seems the #! line must be the first line of a perl script, so this is impossible?

The shebang (#!/path/to/interpreter) is only used on unix-like systems. And it has to be the first line. On Windows systems, the shebang is not used, instead file ending associations may be used: you can associate the .pl file ending with the perl interpreter.
Command line switches in the shebang will be interpreted by the perl interpreter, regardless of platform.
A safe way to launch perl scripts on all platforms is to actually use the perl command. It will be available in case of an successfull Perl installation. E.g. perl myscript.pl instead of ./myscript.pl. The second options requires that the file is set as "executable" on *nix systems.

#! must be the first two characters of the file, because that's where the kernel looks for them when it tries to launch your file. They're part of a directive for the OS (called the shebang line), and the OS knows nothing about Perl.
If you use a standard Perl installer (such as ExtUtils::MakeMaker) to installer your script, just use #!perl and the installer will adjust any existing #! line for your system.

It's not possible. The "#!" is looked at by the exec*() family of Unix functions, to determine how to run the file. So you can't do any scripting there.
It's not all that useful anyway, since the Windows command prompt (or CreateProc() function, but I'm not sure whether that can be used to launch a batch file) doesn't look for the #!.

Related

How can I simply use one perl script in any folder?

I have just added this script to PATH variable, but it does not work.
I need to use it in any directory as:
perl script.pl SOME ARGUMENTS
I have windows 7 Ultimate.
Thank you for advices!
While the system is using PATH to find the program to run, the system is executing perl, not script.pl.
Either tell perl to search PATH for the script,
perl -S script.pl SOME ARGUMENTS
Or launch the script directly.
script.pl SOME ARGUMENTS
Windows will use file associations to determine how to launch the file in the latter case.

Unable to execute Perl script unless Perl is inserted before script name

Running Lubuntu -
Beginner Perl programmer
Script is XXX.pl located at ~/projects/XXX/XXX.pl
First line is the shebang
#!/usr/bin/perl
Permission to run is set to Anyone.
In directory ~/projects/XXX, the command
~/projects/XXX$ perl XXX.pl
works as desired, but the command
~/projects/XXX$ XXX.pl
Fails with XXX.pl: command not found
What am I missing ?
The two usual options to execute your Perl script are:
perl XXX.pl
or
./XXX.pl
Both ways assume that your current working directory contains the script XXX.pl, otherwise it won't work.
As already pointed out by jm666 in the comments, you can usually not execute a program or script from your current working directory without prepending ./, primarily because of security reasons. Now, you may wonder why it's necessary.
Explanation:
Your shell uses the contents of an environment variable called $PATH to find out about where external commands (non-builtin programs) are located in your filesystem. If you want to see what's in $PATH, just type the following in your shell:
echo $PATH
Now you can see that the $PATH variable does NOT contain your current working directory. The consequence is that your shell is not able to find the program XXX.pl. By prepending ./ you instruct the shell to execute the program which comes after.
But there are two requirements if you want to execute your Perl script with ./script.pl:
The script has to be executable (check with ls -l)
The first line (shebang line) has to be #!/path/to/your/perl because your shell needs that information to find the perl interpreter in order to run your script
However, #1 and #2 are NOT required when you execute your script with
perl XXX.pl
because it invokes the perl interpreter directly with your script.
See how to make Perl scripts executable on Linux and make the script itself directly executable with chmod for some more details.
Can the script be found?
Is . in your path? If it's not, add it to your path, or use ./XXX.pl instead of XXX.pl.
Can the script be executed?
Do you have execute permission to the file? Fix using chmod u+x XXX.pl.
Is the interpreter correct?
which perl will tell you which interpreter is used when you use perl XXX.pl. That's the path that should be on your shebang (#!) line.

Cygwin usr/bin/perl: bad interpreter : Permission denied

Hello I'm trying to run a perl script on a Windows 64 bit. I'm getting the error like this :
/usr/bin/perl : bad interpreter : Permission denied
I have my perl script on my windows 64 bit C:\test\perlscripts\testperl.pl.
You probably saved the Perl script with DOS style line endings. The shell is looking for a file called /usr/bin/perl<CR>.
Save your files with Unix-style line endings. My .vimrc which I use with my natively compiled vim and gvim has:
set fileformat=unix
set fileformats=unix,dos
Check your editor's settings for the appropriate options.
To fix line endings in a particular file, use $ dos2unix filename.
You may not install Perl in default cygwin64 package. Please ensure that you have Perl at /usr/bin/perl.exe.
If it is not there, run setup-x86_64.exe again and select Perl interpreter.

Series of Perl Scripts. BASH, BATCH, Shell?

I have a series of perl scripts that I want to run one after another on a unix system. What type of file would this be / could I reference it as in documentation? BASH, BATCH, Shell Script File?
Any help would be appreciated.
Simply put the commands you would use to run them manually in a file (say, perlScripts.sh):
#!/bin/sh
perl script1.pl
perl script2.pl
perl script3.pl
Then from the command line:
$ sh perlScripts.sh
Consider using Perl itself to run all of the scripts. If the scripts don't take command line arguments, you can simply use:
do 'script1.pl';
do 'script2.pl';
etc.
do 'file_name' basically copies the file's code into the current script and executes it. It gives each file its own scope, however, so variables won't clash.
This approach is more efficient, because it starts only one instance of the Perl interpreter. It will also avoid repeated loading of modules.
If you do need to pass arguments or capture the output, you can still do it in a Perl file with backquotes or system:
my $output = `script3.pl file1.txt`; #If the output is needed.
system("script3.pl","file1.txt"); #If the output is not needed.
This is similar to using a shell script. However, it is cross-platform compatible. It means your scripts only rely on Perl being present, and no other external programs. And it allows you to easily add functionality to the calling script.

Passing arguments to script, getting: "Use of uninitialized value $ARGV[0]"

Problem: Windows XP is not passing command line arguments to perl scripts.
Symptom: a simple command like:
say "Argument 1 (\$ARGV[0]) is: $ARGV[0], argument 2 (\$ARGV[1]) is: $ARGV[1].";
Resulted in:
Use of uninitialized value $ARGV[0] in concatenation (.) or string at...
Solution:
The root problem is in Windows XP. The default method for starting perl passes only the first variable, which is the script name. Result is that $ARGV[0] is uninitialized.
The fix is to edit the Windows registry at:
\HKEY_CLASSES_ROOT\Perl\shell\Open\command
And make the entry:
"C:\Perl\bin\perl.exe" %*
Result is:
C:\whatever>perl argtest.pl 1 2
Argument 1 ($ARGV[0]) is: 1, argument 2 ($ARGV[1]) is: 2.
Thanks especially to David W who pointed me in the right direction.
Note that #ARGV in Perl is not quite like argv in C.
C Perl
Name of the program argv[0] $0
1st argument argv[1] $ARGV[0]
2nd argument argv[2] $ARGV[1]
n-th argument argv[n] $ARGV[n-1]
So if you provide one command line arguments to a Perl script, it will be found in $ARGV[0]. $ARGV[1] will be uninitialized.
Download Cygwin and test your code in the Cygwin environment. I bet this is a Windows issue. (If you're a Unix head, you'll like Cygwin because it gives you the Unix/Linux like environment on your Windows machine. I don't use Windows without it.)
Windows uses suffixes to determine what program opens what files. Is your Perl script called argtest, argtest.bat or argtest.pl?
On Windows, make sure all of your Perl scripts use the *.pl suffix, so Windows will use whatever Perl parameter to execute them. Windows doesn't use the shebang.
Another possible issue: On Windows XP, I had a problem with Perl scripts with parameters because Windows had this as an execution string:
perl %1
which would execute the Perl program with my script, but ignore the parameters. I had to change this to:
perl %*
Unfortunately, Windows Vista through Windows 8 changed the way this is set. However, I have Windows 7 and don't have this issue. I did make sure to install Perl under C:\Perl and not C:\Program Files\Perl because of the space in the directory name. I also have Strawberry Perl installed.
There is a special Windows environment variable called PATHEXT. This allows you to type in foo instead of foo.pl. If Windows can't see how to execute your file, Windows goes through %PATHEXT and tries appending various suffixes until it finds one that works. You might want to append .PL to that environment variable, so you can type in foo instead of foo.pl all the time.
There are two ways that Windows knows it is supposed to use Perl to execute a program.
The command line begins with the perl executable and the name of the script to be run is provided as a command line argument. This is how it works on Unix and other environments, too.
Your system associates one or more extensions, such as .pl, .pm, and/or .cgi with the Perl application, and Windows will launch Perl when you type a filename with one of those extensions or click on a file with one of those extensions in the Windows explorer.
You have invoked your script simply as
argtest 1 2
and not one of
perl argtest 1 2
argtest.pl 1 2
That makes me think that Perl is not the first application that gets to look at the file referred to by argtest. Perhaps there is a file called argtest.bat or argtest.exe which has the task of getting Perl to run your Perl code. For some reason this intermediate program is not passing the command line arguments that you provide on to the Perl application.
Provide the code for this intermediate file and we can help some more.
UPDATE: David W proposes a 3rd way -- setting the PATHEXT environment variable to inclue .pl files and invoking argtest from the command-line -- see his answer.
Then if Window's file association with the .pl extension was messed up, say, set as just C:\Dwimperl\perl\bin\perl" and not "C:\Dwimperl\perl\binperl %*" then the OP would get the behavior that he describes.
In perl file name is not part of the array of arguments. At least in the test I did you must remove ARGV[2] or pass three arguments, like argtest 1 2 3