Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Find the full path of the script at run time

by ibanix (Hermit)
on Mar 12, 2003 at 23:11 UTC ( [id://242532]=perlquestion: print w/replies, xml ) Need Help??

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

Hello fellow monks!

How would I find the full path to a script at the time it is invoked? eg, if the script is /home/foo/script.pl, return all of that.

I need this to work on Win32 also. I'm about to go dive into perlvar and see if I can find a built-in that does this, but I thought I'd ask my wise masters first. :-)

Cheers,
ibanix

$ echo '$0 & $0 &' > foo; chmod a+x foo; foo;

Replies are listed 'Best First'.
Re: Find the full path of the script at run time
by mojotoad (Monsignor) on Mar 13, 2003 at 00:01 UTC
    Merely using Cwd and get_cwd() isn't going to cut the mustard -- mainly because you can invoke a script from directories other than your current working directory. Use abs_path() instead (or fast_abs_path()):

    #!/usr/bin/perl -w use Cwd qw(abs_path); print "I am ", abs_path($0), "\n";

    Note that abs_path() will also resolve chains of soft links, so if that's not what you want you might use rel2abs($0) from File::Spec, or you will have to back up a bit and manipulate $0 directly, possibly with get_cwd() and File::Spec for generating the cannonical path.

    And in any of these cases, use File::Spec for slicing and dicing pathnames.

    You can also just simply use FindBin, except that certain people might fuss at you for reasons such as these.

    You might also find these nodes of interest, from Q&A:

    Matt

      Thanks mojotoad.

      I'm not sure the abs_path method will work for me. I'm trying to share a set of scripts and associated files via a Windows network share. Here's what happens if I run
      use Cwd qw(abs_path); print "I am ", abs_path($0), "\n";
      via a script located on the network share:
      C:\>path_test.pl Cannot chdir to \\flash\it\NOC-TO~1\PATH_T~1.PL:No such file or direct +ory at \\flash\it\NOC-TO~1\PATH_T~1.PL line 2
      I'm guessing Cwd has issues with UNC paths.

      Perhaps I'll have to use $0 and hope for the best.

      $ echo '$0 & $0 &' > foo; chmod a+x foo; foo;
        Note my update above regarding rel2abs() from File::Spec.

        In this case, however, you are bumping into the difference between abs_path() and fast_abs_path(): both generate cannonical paths, but the first relies on the OS by repeatedly issuing chdir() on path fragments in order to verify that Cwd and the OS are in agreement. This will cause problems if the path in question is hypothetical or if you do not have permission to traverse the path tree.

        fast_abs_path(), on the other hand, does this "visually" without checking with the OS -- as a consequence it's much faster, but potentially more risky.

        99% of the time this is not a problem for most paths. If your paths have a tendency to utilize soft links that cross volumes and mount points (therefore potentially different filesystem types), then it can be a problem. Since Windows doesn't have soft links (shortcuts aren't soft links) then you shouldn't have a problem using fast_abs_path().

        Wrote a song about it once. Like to see it? Here it is.

        Matt

Re: Find the full path of the script at run time
by Cabrion (Friar) on Mar 12, 2003 at 23:57 UTC
    I use $0 and strip the filename when I just want the path. You can use $^O to figure out the OS and thus how to deal with WIN32, Mac, UNIX & VMS paths.
      Thanks. I think this is what I will be going for.

      I also found This thread, and was considering FindBin, but apparently FindBin is broken.

      I'd still be interested in other options. If my script is invoked as ..\..\script.pl, won't that set $0 to ..\..\script.pl ?

      Cheers,
      ibanix

      $ echo '$0 & $0 &' > foo; chmod a+x foo; foo;
        Actually FindBin is broken in more than just this way. I've had cases where scripts that had limited permissions (CGI), where FindBin just died. It looks like it tries to verify the existence of the path it found, occasionally ending up in directories where it has no visiting rights. I'm not sure that is indeed what it does, — if so, it's likely File::Spec that is to blame; but this situation makes it useless for situations where it would be most useful.

        Anyway, to answer your question: yes, $0 would be set to ..\..\script.pl. That's where tye's solution, rel2abs, would again come to the rescue. A demo of a full solution, as tye merely mentioned the function name:

        use File::Spec::Functions 'rel2abs'; print rel2abs($0);

        update: Oh dear, it doesn't. The double dots are still in the created path. For Unix, that is the safest, as you never know which "directory" is actually just a link to another directory, so by following "foo/.." you could end up in an entirely different directory from where you started from.

        It doesn't look as neat, but it works just as well.

Re: Find the full path of the script at run time
by Nkuvu (Priest) on Mar 13, 2003 at 00:04 UTC

    How is the script called? In some brief testing I found that using the file association in Windows caused $0 to contain the full path to the script (something like scriptname.pl from the script's directory). Calling the script via perl \full\path\to\script.pl (executing from either the directory containing the script, or another directory) worked as well. Calling the script from within the script's directory using perl scriptname.pl failed -- only the script name was in $0.

    Not sure how $0 is affected in non-Windows OSs, though...

Re: Find the full path of the script at run time
by data64 (Chaplain) on Mar 13, 2003 at 06:12 UTC

    I usually use the below on ActiveState perl. Although I believe it also works on Linux.

    use strict; use warnings; use English; use File::Basename qw( dirname ); use File::Spec::Functions qw( rel2abs ); my $script_dir = rel2abs( dirname( $PROGRAM_NAME ) ); print "$script_dir\n";

    You could leave out the "use English" and replace $PROGRAM_NAME with $0


    Update:
    There is an implicit assumption in the above code, that you are not talking about a CGI script.

    You should also look at How do I get the full path to the script executing?


    data64
Re: Find the full path of the script at run time
by htoug (Deacon) on Mar 13, 2003 at 11:45 UTC
    The easy solution is to use cwd and $0 and massage that to get rid of ..'s etc. as described in the previous posts.

    However this will not always work! Don't forget that your script can come to the perl-interpreter from many sources, even from current input (or via the -e-flag.

    You will probably be able to find a solution to your problem, that will hold in some/most/nearly all(?) cases, but be prepared for it to fail miserably. One of the reasons that FindBin may fail, is that parts of the path may have disappeared between the time when your script was started and now. So the best you can hope for is the name of the script (if any) as it was at the time when your script started. And I would be very wary of trying to eliminate ..'s in the path, as the meaning of them migth have changed in the meanwhile.

    Trying to do it correctly cross-platform just makes my mind boggle :-)

Re: Find the full path of the script at run time
by PriNet (Monk) on Mar 13, 2003 at 05:03 UTC
    i use the following to determin my "real" path ibanix...
    my($Root) = substr($ENV{'PATH_TRANSLATED'},0,length($ENV{'PATH_TRANSLATED'})-length($ENV{'PATH_INFO'}));


    you mean there's any easier way?

      Doesn't this work only for CGI scripts?

      -- 
              dakkar - Mobilis in mobile
      
Re: Find the full path of the script at run time
by tachyon (Chancellor) on Mar 13, 2003 at 09:37 UTC
    use Win32; my $cwd = Win32::GetCwd

    The latest version supports UNC paths

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://242532]
Approved by Mr. Muskrat
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2024-04-23 15:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found