maletin has asked for the wisdom of the Perl Monks concerning the following question:

How can I find out the absolute path of my source-code? I wrote a test-script that uses the function caller():

#! perl -w # filetest.t # should be invoked from different directories (prove -r). use strict; use warnings; use Test::More tests => 2; use File::Basename; use File::Spec; my $filename = (eval{caller})[1]; diag("filename of this test-script: $filename"); my $dirname = dirname( $filename ); diag("dirname of this test-script: $dirname"); my $location = File::Spec->catfile( $dirname, 'non-existing-file' ); diag("testing a non existing file: $location"); cmp_ok( defined -f $location, '==', 1, 'this test should fail' ); $location = File::Spec->catfile( $dirname, 'filetest.t' ); diag("testing an existing file: $location"); cmp_ok( defined -f $location, '==', 1, 'this file should exist' );

my output of perl lib/t/filetest.t:

1..2 # filename of this test-script: lib/t/filetest.t # dirname of this test-script: lib/t # testing a non existing file: lib/t/non-existing-file not ok 1 - this test should fail # Failed test 'this test should fail' # at lib/t/filetest.t line 19. # got: # expected: 1 # testing an existing file: lib/t/filetest.t ok 2 - this file should exist # Looks like you failed 1 test of 2.
How can I get the absolute filename instead of "./lib/t/filetest.t"?

Replies are listed 'Best First'.
Re: absolute pathname
by ikegami (Patriarch) on Aug 12, 2008 at 20:57 UTC
      rel2abs() has problems with volumes:
      If $base is not present or ’’, then Cwd::cwd() is used. If $base is relative, then it is converted to absolute form using "rel2abs()". This means that it is taken to be relative to Cwd::cwd(). On systems with the concept of volume, if $path and $base appear to be on two different volumes, we will not attempt to resolve the two paths, and we will instead simply return $path.

        That doesn't seem to apply to Windows.

        D:\>perl c:script.pl C:\path\script.pl D:\>perl c:..\ikegami\script.pl C:\path\script.pl

        I could still apply to other systems, though (VMS?)

        Update: Looking at the source, it uses getdcwd (as opposed to getcwd) with the appropriate volume, returning the correct path even when different volumes are involved.

Re: absolute pathname
by Lawliet (Curate) on Aug 12, 2008 at 22:57 UTC
    use Cwd "abs_path"; my $path = abs_path($0);

    Works for me ^^

    I'm so adjective, I verb nouns!

    chomp; # nom nom nom

      thank you. here is the difference between abs_path and rel2abs():

      $ cd $HOME $ ln -s /tmp softlink $ perl softlink/mylog.pl
      main:: path/mylog.pl (23)> abs_path=/tmp/mylog.pl main:: path/mylog.pl (26)> rel2abs=/home/maletin/softlink/mylog.pl MyLog::init /home/maletin/MyLog.pm (11)> INIT MyLog::path /home/maletin/MyLog.pm (16)> /home/maletin/MyLog.pm

      $ cat /tmp/mylog.pl

      #! perl -w # mylog.pl # using a package that print it's absolute filename. use strict; use warnings; use Log::Log4perl; use Cwd qw( abs_path ); use lib $ENV{HOME}; # location of MyLog.pm use MyLog; my $conf = q( log4perl.category.Log = INFO, Screen log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.Screen.layout.ConversionPattern = %l> %m %n ); Log::Log4perl->init( \$conf ); my $log4perl_logger = Log::Log4perl->get_logger('Log'); my $abs_path = abs_path($0); $log4perl_logger->info("abs_path=$abs_path"); my $rel2abs = File::Spec->rel2abs($0); $log4perl_logger->info("rel2abs=$rel2abs"); MyLog->init($log4perl_logger); MyLog->path();

      $ cat $HOME/MyLog.pm

      package MyLog; use strict; use warnings; my $my_logger = undef; sub init { my ( $class, $logger ) = @_; $my_logger = $logger; $my_logger->info('INIT'); } sub path { my $path = ( eval { caller(0) } )[1]; $my_logger->info($path); return $path; } 1;

      but because of Windows, i will use the version with "softlink" in the filename.
      Not for me
      D:\>perl c:script.pl D:\C:script.pl

      File::Spec::Win32's rel2abs is a wrapper around Cwd that solves this problem.

Re: absolute pathname
by eyepopslikeamosquito (Archbishop) on Aug 12, 2008 at 21:28 UTC

      It fails miserably — dies of errors — when the work directory and the script are on different volumes.

      FindBin also has other problems.