Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Getting logical path from Perl?

by mathomp4 (Novice)
on Mar 08, 2021 at 13:24 UTC ( [id://11129329]=perlquestion: print w/replies, xml ) Need Help??

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

I am most definitely not a Perl guru, so I might be asking a simple question but...I can't figure it out. I work on a model that uses Perl for some scripting that creates other scripts. I also work on a system where directories can "move" because of NFS. As an example, I have a directory on the system:

/discover/nobackup/mathomp4

That is actually a path through a symlink:

$ pwd -L /discover/nobackup/mathomp4 $ pwd -P /gpfsm/dnb44/mathomp4

Every so often, due to disk systems filling up, they might have to move us from, say, dnb44 to dnb45, and if I use Perl to make a script before that move, well, things break. So, it would be good for Perl to use the logical and not physical path. For example, I have a script that wants to know what directory it was called from. My hope after reading the FindBin docs:

$Bin - path to bin directory from where script was invoked $RealBin - $Bin with all links resolved

was that Bin would do it, but it seems to be the same as RealBin:

$ cd $HOME $ cat /discover/nobackup/mathomp4/MyTestScript/bin/test.pl #!/usr/bin/env perl use FindBin; use File::Basename; my $fvroot = dirname($FindBin::Bin); print "Using Bin: $fvroot\n"; my $fvroot2 = dirname($FindBin::RealBin); print "Using RealBin: $fvroot2\n"; $ /discover/nobackup/mathomp4/MyTestScript/bin/test.pl Using Bin: /gpfsm/dnb44/mathomp4/MyTestScript Using RealBin: /gpfsm/dnb44/mathomp4/MyTestScript

Dang. So is there any way for Perl to see the logical path rather than the physical one?

Replies are listed 'Best First'.
Re: Getting logical path from Perl?
by hippo (Bishop) on Mar 08, 2021 at 13:59 UTC

    Does this do what you want?

    $ cat /tmp/foo/mydir.pl #!/usr/bin/env perl use strict; use warnings; use Path::Tiny; my $path = path ($0); my $dir = $path->parent->stringify; print "\$0: $0\n"; print "Path::Tiny: $dir\n"; $ ls -l /tmp/foo lrwxrwxrwx. 1 user users 3 Mar 8 13:47 /tmp/foo -> bar $ /tmp/foo/mydir.pl $0: /tmp/foo/mydir.pl Path::Tiny: /tmp/foo $

    🦛

      Good news, it does what we want. Bad news, it depends on the calling script using the logical path to the script, which might expose the same issue. I'm beginning to think we might just need to rewrite some scripting to be more robust...

      That said, thanks for all the lessons in Perl!

Re: Getting logical path from Perl?
by Tux (Canon) on Mar 08, 2021 at 15:47 UTC

    I interpret the question as : I only want to run this script if it is invoked from the symlinked folder.

    Use Path::Tiny if you want to stay portable (as posted earlier).

    Check -l, readlink, and Cwd::abs_path to fill your needs.

    #!perl use Cwd qw( getcwd abs_path ); my ($DIR, $CMD) = $0 =~ m{^(.*)/([^/]+)$}; ! $CMD && ! -d $DIR and ($DIR, $CMD) = (getcwd, $DIR); # "." in $PATH +and script invoked without ./ -l $DIR or die "$DIR is not the symlinked folder. Running like this is + dangerous!\n"; say "Current dir : ", getcwd; say "Invoking folder: ", $DIR; say "Symlink : ", readlink $DIR; say "Abs path: : ", abs_path $DIR;
    $ mkdir -p tmp/test-a $ ln -s test-a tmp/test $ ln -s tmp/test test $ vi tmp/test/test.pl -- paste above code and save $ perl test/test.pl Current dir : /home/tux Invoking folder: test Symlink : tmp/test Abs path: : /home/tux/tmp/test-a

    Enjoy, Have FUN! H.Merijn
Re: Getting logical path from Perl?
by talexb (Chancellor) on Mar 08, 2021 at 13:54 UTC

    If pwd -L gives you the answer you want, can you just grab that value when you need it?

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

      The issue with pwd -L is that we don't always run these scripts from the bindir. So, we'd have to chdir to do so and:

      $ cat /discover/nobackup/mathomp4/MyTestScript/bin/test-pwd.pl #!/usr/bin/env perl use FindBin; use File::Basename; my $fvroot = dirname($FindBin::Bin); print "Using Bin: $fvroot\n"; my $fvroot2 = dirname($FindBin::RealBin); print "Using RealBin: $fvroot2\n"; chomp($pwdL = `pwd -L`); print "Current pwd -L: $pwdL\n"; chdir($fvroot); chomp($pwdL2 = `pwd -L`); print "After pwd -L: $pwdL2\n" $ /discover/nobackup/mathomp4/MyTestScript/bin/test-pwd.pl Using Bin: /gpfsm/dnb44/mathomp4/MyTestScript Using RealBin: /gpfsm/dnb44/mathomp4/MyTestScript Current pwd -L: /home/mathomp4 After pwd -L: /gpfsm/dnb44/mathomp4/MyTestScript

      So, it's not logical because the chdir didn't go to the logical path! That said, I haven't yet tested the Path::Tiny yet.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11129329]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (1)
As of 2024-04-25 19:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found