9

Code

#!/usr/bin/perl -I/root/Lib/ 
use Data::Dumper;
print Dumper \@INC; 

The above code file name is test.pl and the permission is 755.

When I am running the program using /usr/bin/perl test.pl the output of the @INC contains "/root/Lib" at the end. It is like push in to @INC.

/usr/bin/perl test.pl Output

$VAR1 = [
          '/etc/perl',
          '/usr/local/lib/perl/5.10.0',
          '/usr/local/share/perl/5.10.0',
          '/usr/lib/perl5',
          '/usr/share/perl5',
          '/usr/lib/perl/5.10',
          '/usr/share/perl/5.10',
          '/usr/local/lib/site_perl',
          '.',
          '/root/Lib/'
        ];

But when I am running the program using ./test.pl the output of the @INC contain "/root/Lib/" contain first as well as end also. It is like unshift and push.

./test.pl output

$VAR1 = [
          '/root/Lib/',
          '/etc/perl',
          '/usr/local/lib/perl/5.10.0',
          '/usr/local/share/perl/5.10.0',
          '/usr/lib/perl5',
          '/usr/share/perl5',
          '/usr/lib/perl/5.10',
          '/usr/share/perl/5.10',
          '/usr/local/lib/site_perl',
          '.',
          '/root/Lib/'
        ];

So I want to know what is the difference between ./test.pl and /usr/bin/perl test.pl ?

muruga
  • 2,092
  • 2
  • 20
  • 28
  • +1 that's surprising behaviour, investigating... – msw Jul 08 '13 at 11:31
  • 4
    if you did perl -I/root/Lib test.pl it would be the same. The shebang on line one is used as the command when you do ./test.pl – KeepCalmAndCarryOn Jul 08 '13 at 11:34
  • 1
    Curiouser and curiouser: if `L` is `/root/lib` I get output of `L, L, ...` for the shebang execution and `L, ...` for the /usr/bin/perl invocation. What OS and (if applicable) perl package are you using? – msw Jul 08 '13 at 11:47
  • Also, the values (if any) the environment variables of PERL5LIB and PERLLIB are relevant. – msw Jul 08 '13 at 12:07
  • Do you have multiple perl installations? – devnull Jul 08 '13 at 12:50
  • See also [What is the difference between "`perl test.pl`" and "`./test.pl`"](http://stackoverflow.com/questions/11970541/what-is-the-difference-between-perl-test-pl-and-test-pl). Not identical, but closely related. – Jonathan Leffler Jul 17 '13 at 16:03

3 Answers3

7

There are two questions lurking here. The headline question is "What's the difference between ./test.pl and perl test.pl?", while the secondary question is "Why is /root/Lib added at the front of @INC when the script is run as ./test.pl and not when run as perl test.pl?"

An answer, not necessarily applicable to your situation, is that ./test.pl runs the Perl interpreter specified by the shebang (/usr/bin/perl), whereas perl test.pl runs whatever Perl interpreter is found first on your $PATH (or aliases or functions). These need not be the same version of Perl. For me, they very seldom are the same version of Perl; the one in /usr/bin is usually relatively old and the one on my $PATH is relatively new (5.8.x vs 5.18.x, for example).

Working with Perl 5.12.4 (ouch; that's old) from /usr/bin on my machine, and using your script, I see:

$ perl test.pl
$VAR1 = [
          '/root/Lib/',
          '/Library/Perl/5.12/darwin-thread-multi-2level',
          '/Library/Perl/5.12',
          '/Network/Library/Perl/5.12/darwin-thread-multi-2level',
          '/Network/Library/Perl/5.12',
          '/Library/Perl/Updates/5.12.4',
          '/System/Library/Perl/5.12/darwin-thread-multi-2level',
          '/System/Library/Perl/5.12',
          '/System/Library/Perl/Extras/5.12/darwin-thread-multi-2level',
          '/System/Library/Perl/Extras/5.12',
          '.'
        ];
$ ./test.pl
$VAR1 = [
          '/root/Lib/',
          '/root/Lib/',
          '/Library/Perl/5.12/darwin-thread-multi-2level',
          '/Library/Perl/5.12',
          '/Network/Library/Perl/5.12/darwin-thread-multi-2level',
          '/Network/Library/Perl/5.12',
          '/Library/Perl/Updates/5.12.4',
          '/System/Library/Perl/5.12/darwin-thread-multi-2level',
          '/System/Library/Perl/5.12',
          '/System/Library/Perl/Extras/5.12/darwin-thread-multi-2level',
          '/System/Library/Perl/Extras/5.12',
          '.'
        ];
$

Note that here the /root/Lib name is added once or twice to @INC. My best guess is that when you use perl test.pl, Perl scans the shebang and adds the -I option if finds there. When you use ./test.pl, the kernel runs /usr/bin/perl -I/root/Lib test.pl (where we can negotiation on whether the name test.pl appears on the command line; the key point is that the -I/root/Lib does appear), so Perl adds /root/Lib once because of the explicit -I provided by the kernel, and then adds another because it parses the shebang line.

See: perldoc perlrun for many more details.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

You should use lib instead. That way, execution is consistent.

#!/usr/bin/perl

use lib qw( /root/Lib/ );

use Data::Dumper;
print Dumper \@INC; 

See http://perldoc.perl.org/lib.html

shawnhcorey
  • 3,545
  • 1
  • 15
  • 17
2

When you run it as perl test.pl, among the first things it does is look to see if there is a line starting with #!. If it finds one it tries to act as if it were called with those arguments.

So the following adds warnings

#! perl -w

If you run it as ./test.pl your system actually runs it with those arguments. Perl really doesn't have a way of knowing that it was called implicitly like that. So Perl just parses that line itself like it did previously.

In your case that means that /root/Lib/ will be added to @INC twice.

The reason it appears at the beginning of the list; is that when Perl is actually called with that option, it adds it before it has a chance to load '@INC with anything.
If it gets added when parsing #!, it has already populated @INC so it adds it at the end.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129