What is the difference between "perl test.pl" and "./test.pl"? - perl

I have observed that there are two ways of executing a perl program:
perl test.pl
and
./test.pl
What is the exact difference between these two and which one is recommendable?

I will rephrase slightly what other answers stated.
The first case will run the program called "perl" - presumably, a Perl language interpreter, and pass the value "test.pl" to it as the first parameter. Please note that this will do one of 3 things, depending on what "perl" is and what "test.pl" is:
If "perl" does not exist as an executable in your $PATH or a shell alias (check by running which perl), your shell will try to find a non-existing executable, and fail with perl: Command not found error.
If "perl" is an executable in your path (or a shell alias) that is NOT actually a Perl interpreter program, that will get executed instead. As example, try this in csh:
alias perl echo
which perl # Will print "perl: aliased to echo"
perl test.pl # Will print "test.pl". NOT what you intended!
unalias perl
This will execute your "perl" alias and simply echo the word "test.pl"
If "perl" is an executable in your path that IS a real perl interpreter, it will pass "test.pl" to it as a first parameter. In that case, Perl interpreter will treat this parameter (as it doesn't start with a "-") as the name of a file containing Perl code to execute and try to read the file in, compile it as Perl code and execute it.
Note that, since the program being run is actually "perl" and "test.pl" is just a text file being read in, "test.pl" does NOT need to have the "execute" Unix file permission.
The second case, shell will try to find a file called "test.pl" in your current directory, and - if it exists AND is executable - try to execute it as a program.
If the file does not exist OR if the execute bit on it is not set, the shell will fail with "command not found" error.
If the file has the execute bit set, shell (or actually process loader in Unix kernel) will try to execute it. The rules by which Unix executes a given executable file is governed by the first 2 bytes of the file, aka "magic number".
For a VERY good in-depth coverage of how magic numbers work, see "How does the #! work?" question on SO.
In a special case where the "magic number" is "#!" (aka "shebang"), the loader will read the first line of the file, and treat the contents of that line (sans the first 2 bytes) as a command to run instead of the given executable file; and append the path to the executable file as one more parameter to the command it read from shebang line. As examples:
if "test.pl" is a text file with a first line of #!/bin/sh -x, the kernel will execute /bin/sh -x ./test.pl.
if "test.pl" is a text file with a first line of #!/usr/bin/perl, the kernel will execute /usr/bin/perl ./test.pl.
if "test.pl" is a text file with a first line of #!perl, the kernel will execute perl ./test.pl.
if "test.pl" is a text file with a first line of my $var = 1; (or any other first 2 bytes it doesn't know what to do with), it will either error out or (at least on RedHat Linux) will pretend that there was an implied #!/bin/sh shebang and try to execute the file as Bourne Shell script. Which will of course fail since it was Perl code, not shell script

In the first case you are starting the perl interpreter and asking it to use your file and run it.
In the second case you are asking your shell to execute your file. This requires that the file starts with
#!/<path to perl>/perl
and that the file has the execute bit set.
The best method to use is the one that fits your usecase the best.

The first one will always run the script as the perl code.
The second one will do it only in case the perl is specified in she-bang. Otherwise it will run it as shell code or whatever is specified in she-bang (if there is no she-bang at all it will run as current shell code).
The first one will be executed even noexec mount option is enabled.
The second one will fail in that case.
The same stuff with execute bit. The first one will work if +x isn't setted, the second will fail.

The first executes the program using the perl that is found first in your $PATH. The second uses whatever shebang line in the program says.

If u set the executable permissions to the file , then you can run the file by ./ or else run using perl filename.pl

perl test.pl
Specify to the shell that you want the current Perl executable (as is found in your $PATH) to execute the test.pl file that is located in your $PATH.
Run which perl to quickly see what version of perl is the default
Run echo $PATH to see where the '.' (current directory) is. ALL directories BEFORE the '.' will be checked FIRST for the test.pl file! Use ./test.pl instead so the shell looks in the current directory only...Unless you want it to hunt in the $PATH for the test.pl file.
./test.pl
Specify to the shell that you want the test.pl file, in the current directory, to be run by the executable as specified inside the test.pl file at the line with the she-bang (line that starts with #!).

Related

How to make Perl script executable?

I have given a perl script file executable permission on a Unix based system, but when I try to execute the file I get a "command not found" error. I have #!usr/local/bin/perl at the start of the script file.
At the top of your script, replace the #!usr/local/bin/perl with #!/usr/bin/perl notice the root '/' prior to the usr/
And you can try perl <filename> keyword to run the file instead of ./<filename>, using perl keyword should run the script regardless of the shebang line at the top of your script.
replace your first line #!usr/local/bin/perl with #!usr/bin/perl(which is called Shebang). Then you can run the file with perl <Path To File>.

Could someone tell me what this means in Perl

I'm new to Perl and was hoping someone could tell me what this means exactly
eval 'exec ${PERLHOME}/bin/perl -S $0 ${1+"$#"}' # -*- perl -*-
if 0;
This is explained in perldoc perlrun:
-S
makes Perl use the PATH environment variable to search for the program
unless the name of the program contains path separators.
...
Typically this is used to emulate #! startup on platforms that don't
support #! . It's also convenient when debugging a script that uses
#! , and is thus normally found by the shell's $PATH search
mechanism.
This example works on many platforms that have a shell compatible with
Bourne shell:
#!/usr/bin/perl
eval 'exec /usr/bin/perl -wS $0 ${1+"$#"}'
if $running_under_some_shell;
The system ignores the first line and feeds the program to /bin/sh,
which proceeds to try to execute the Perl program as a shell script.
The shell executes the second line as a normal shell command, and thus
starts up the Perl interpreter. On some systems $0 doesn't always
contain the full pathname, so the -S tells Perl to search for the
program if necessary. After Perl locates the program, it parses the
lines and ignores them because the variable
$running_under_some_shell is never true. If the program will be
interpreted by csh, you will need to replace ${1+"$#"} with $* ,
even though that doesn't understand embedded spaces (and such) in the
argument list. To start up sh rather than csh, some systems may
have to replace the #! line with a line containing just a colon,
which will be politely ignored by Perl.
In short, it mimics shebang behavior for platforms that have shells compatible with Bash.
It's valid both as shell script and as a Perl program. It is used to run the Perl interpreter after all on systems where the shebang doesn't work, for some reason. It's rarely seen these days but used to be common in the early 1990s.
The comment is just a comment, but it has special meaning in Emacs, which will open the file in perl mode.
I just read #Zaid's response, which is better and more correct than mine as long as this code is on the first line of the script being executed, and no shebang exists. I've never seen this kind of substitute. Quite interesting, really.
The second line, if 0; is a part of the first line. You can tell since the first line lacks a ;. It would be more obvious if this was one long single line with the comment being after the semicolon.
So it's equivalent to:
if(0) {
eval 'exec ${PERLHOME}/bin/perl -S $0 ${1+"$#"}
}
In perl, 0 will be evaluated to false, and so the eval-clause will never execute. Presumably this condition(the if) was a quick way to disable the line. Perhaps the evaluation was once something real instead of an always-false.
See perl --help, perldoc -f eval and perldoc -f exec for information on the evaluation block itself.
The remaining trickyness (${1+"$#"}) I have no idea about. This isn't perl anyway; it's interpreted by whichever shell exec is launching (Correct me if I'm wrong on this!). If it's bash, I don't think it does anything at all and can be substituted with $#, which is the environment variable holding all commandline arguments (ie #ARGV in perl).

invoking perl scripts

I have perl scripts starting with #!/usr/bin/perl or #!/usr/bin/env perl
First, what does the second version mean?
Second, I use Ubuntu. All the scripts are set as executables. When I try to run a script by simply invoking it's name (e.g. ./script.pl) I get : No such file or directory. when I invoke by perl ./script.pl it runs fine.
Why?
The #!/usr/bin/env perl uses the standard POSIX tool env to work around the "problem" that UNIX doesn't support relative paths in shebang lines (AFAIK). The env tool can be used to start a program (in this case perl) after modifying environment variables. In this case, no variables are modified and env then searches the PATH for Perl and runs it. Thus a script with that particular shebang line will work even when Perl is not installed in /usr/bin but in some other path (which must be in the PATH variable).
Then, you problem with ./script.pl not working: you said it has the executable bit(s) set, like with chmod +x script.pl ? But does it also start with a shebang (#!) line ? That is, the very first two bytes must be #! and it must be followed by a file path (to perl). That is necessary to tell the kernel with which program to run this script. If you have done so, is the path correct ? You want to try the #!/usr/bin/env perl variant ;-)
Using #!/usr/bin/env perl gets around the problem of perl not necessarily being in /usr/bin on every system; it's just there to make the script more portable
On a related note, for your second problem, is there a /usr/bin/perl and/or /usr/bin/env? If not, that would explain why running the scripts directly doesn't work; the shebang isn't handled if you run the script as an argument to perl

Can Perl and Batch run in the same batch file?

I've got a batch script that does some processing and calls some perl scripts.
My question is if there was a way to put the perl code directly into the batch script and have it run both types of scripts.
Active Perl has been doing this for years!
Below is a skeleton. You can only call perl once though. Because passing it the -x switch says that you'll find the perl code embedded in this file, and perl reads down the file until it finds a perl shebang (#!...perl) and starts executing there. Perl will ignore everything past the __END__ and because you told DOS to goto endofperl it won't bother with anything until it gets to the label.
#rem = '--*-Perl-*--
#echo off
perl -x -S %0 %*
goto endofperl
#rem -- BEGIN PERL -- ';
#!d:/Perl/bin/perl.exe -w
#line 10
use strict;
__END__
:endofperl
Yes you can.
In fact this is exactly what the pl2bat tool does: it transforms a perl program into a batch file which embeds the perl program. Have a look to pl2bat.bat itself.
So you can take the .pl, convert it with pl2bat, and then tweak the batch part as you need. The biggest part of the batch code must be put at the end of the file (near the :end_of_perl label) because in the code at the top you are limited to not using single quotes.
However:
this simple approach will not work if you need to embed more that one perl file
this will be a maintenance nightmare.
So I suggest instead to write the whole process in one Perl program.
Update: if you have one script and some Perl modules that you want to combine in a single batch file, you can combine the Perl file using fatpack, and then apply pl2bat on the result.
There is a way to do this, but it wont be pretty. You can echo your perl code into a temp .pl file and then run that file from within your .bat.

How can I run a Perl script on Mac OS X?

How do I run a Perl script on OS X?
You can run your Perl script by invoking the Perl interpreter and giving your file as input:
perl myprogram.pl
The easiest way to run a perl script is with the option:
perl myprogram.pl
However, you may find it more useful to add a shebang line at the top of the perl file.
#!/usr/bin/perl
print "Hello World!\n";
In order to execute this script, you need to add execute permissions to your program. Run:
chmod +x myprogram.pl
Now, in order to run your script, you can simply type:
./myprogram.pl
A good tutorial on Perl in OSX can be found here:
http://www.mactech.com/articles/mactech/Vol.18/18.09/PerlforMacOSX/index.html
A generic documentation on executing Perl code is of course perldoc perlrun.
To answer your question directly:
You can run a perl script on any Unix system by either having the code evaluated and executed from command line:
perl -e 'print "Hello World\n"';
Or you can save your Perl script to a file (customarily having .pl extension, say script1.pl and with the first line being #!/usr/bin/perl) and then you can execute it as any Unix program (after setting proper execute permissions)
/path/to/script/script1.pl
You can also execute a script from a file by running perl interpreter as the command and giving the script as a parameter (in this case execute permissions to the script are not needed):
perl /path/to/script/script1.pl
For some reason the whole directory didn't work for me but I just did
perl ~/Desktop/file.pl
(you could also use any folder that is in your user-folder after the ~/)