in reply to Re: Perl Script own path
in thread Perl Script own path

concatenate the result of cwd() and basename($0) with intervening "/" to get the full path of the script in a OS independent way.

What does the value of Cwd::cwd() have to do with the path of the Perl script? There's no general correlation.

C:\WINDOWS>type C:\Temp\WhereAmI.pl #!perl use strict; use warnings; use Cwd; use English; use File::Basename; my $basename = File::Basename::basename($PROGRAM_NAME); my $abs_path = Cwd::abs_path($PROGRAM_NAME); my $dirname = File::Basename::dirname($abs_path); my $cwd = Cwd::cwd(); print "\$PROGRAM_NAME: $PROGRAM_NAME\n"; print "\$File::Basename::basename(\$PROGRAM_NAME): $basename\n"; print "\$Cwd::abs_path(\$PROGRAM_NAME): $abs_path\n"; print "\$File::Basename::dirname(\$abs_path): $dirname\n"; print "\$Cwd::cwd(): $cwd\n"; exit 0; C:\WINDOWS>perl \Temp\WhereAmI.pl $PROGRAM_NAME: \Temp\WhereAmI.pl $File::Basename::basename($PROGRAM_NAME): WhereAmI.pl $Cwd::abs_path($PROGRAM_NAME): C:/Temp/WhereAmI.pl $File::Basename::dirname($abs_path): C:/Temp $Cwd::cwd(): C:/WINDOWS C:\WINDOWS>

Replies are listed 'Best First'.
Re^3: Perl Script own path
by Marshall (Canon) on Jul 27, 2011 at 07:51 UTC
    Yes, simply Cwd::abs_path($0) appears to work the best. My previous post is not right. I did some more testing but there are a lot of cases and I suspect that there are quirky border cases out there.

    So,
    to get name of program: File::Basename::basename($0);
    to get absolute path: Cwd::abs_path($0); NOT Cwd::Cwd()
    To be portable, you must use abs_path() before doing anything that changes the current working directory, eg chdir().

    I tested on Windows XP and Fedora Linux.
    $0 on Windows was the full absolute path of the executing script, but with Windows style "\" instead of "/".
    $0 on Linux was essentially what was typed into the shell to run the script. Something like this: "../test/whereami.pl" gave exactly that for $0.

    When using Cwd::abs_path($0), on Windows the backslashes ('\') were converted to forward slashes ('/') - the full path stayed the same since $0 was the full path to begin with. A chdir() on Windows had no effect upon the result of abs_path().

    On Linux, abs_path does some text massaging of rel2abs()'s output which itself a result of using Cwd::cwd() so if working directory is changed, abs_path() will be wrong. (oh, abs_path() probably doesn't call rel2abs() but it looks like it does whatever rel2abs() does. Oh, the rel2abs() function in File::Spec... in my Unix test case it concatenates $0 onto what cwd() says. So in my test case, >cd b >../test/whereami.pl, you get a path like: blah../marsh/b/..test/whereami.pl. This is a valid path, but the detour through unrelated directory b is not needed. abs_path() evidently takes this path and eliminates the trip through dir b.

    This is also one of those cases where "use English;" just serves to further confuse the reader because:
    $program_name = File::Basename::basename($PROGRAM_NAME); because of course $0 is NOT the program's name. I don't think there is a good "english name" for $0 because "its sometimes this and sometimes that" is hard to express in one short name!

      __FILE__
        Nice thought. But unfortunately falls short. __FILE__ is $0 on my Fedora Linux box.
        [marsh b]$ cat ../test/filetest #!/usr/bin/perl -w use strict; print "dollar zero is: $0\n"; my $f = __FILE__; print "__FILE__ is: $f\n"; [marsh b]$ ../test/filetest dollar zero is: ../test/filetest __FILE__ is: ../test/filetest