Article 2456 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:2456
Path: feenix.metronet.com!news.ecn.bgu.edu!wupost!howland.reston.ans.net!gatech!hubcap!ncrcae!ncrhub2!ncrgw2!psinntp!internet!sbi!zeuswtc!pivot!bet
From: [email protected] (Bennett Todd @ Salomon Brothers Inc., NY )
Newsgroups: comp.lang.perl
Subject: Re: Name of file symlink points to?
Message-ID: <[email protected]>
Date: 28 Apr 93 03:54:45 GMT
References: <lsloan.735757842@nova> <lsloan.735829331@nova> <[email protected]>
Sender: [email protected]
Organization: Salomon Brothers, Inc.
Lines: 56
Nntp-Posting-Host: sandstorm

In article <[email protected]> [email protected] (Randal L. Schwartz) writes:
>>>>>> In article <lsloan.735829331@nova>, [email protected] (Lance Sloan) writes:
>Lance> Is there any good way to determine what to add to the pathname so that my
>Lance> program sees the symbolic link to /faculty/lsloan/that rather than "that"?
>
>Something like this, perhaps?
>[some typical R. Schwartz code, short, simple, clear, efficient, etc....]

This inspired me; it seemed to be doing most of a job I have occasionally
wanted, but never felt like implementing, namely making canonical pathnames
with _all_ symlinks expanded. I mean to include here expanding symlinks that
occur in the middle of pathnames pointed to by other symlinks. Of course I
couldn't stop there, I had to try to deal with /./ and /../ and automounter
bogosities, and it isn't simple or clean any more. Maybe Randal can repair
this and make it simple again?

#!/usr/local/bin/perl

chop($pwd = `pwd`);

for $orig (@ARGV) {
       $expanded = &Expand($orig);
       print STDERR "$orig -> $expanded\n";
}

sub Expand {
       local($old) = @_;
       local(*_, *dir);
       $old =~ s#^#$pwd/# unless $old =~ m#^/#; # ensure rooted path
       @dir = split(/\//, $old);
       shift(@dir); # discard leading null element
       $_ = '';
       dir: foreach $dir (@dir) {
               next dir if $dir eq '.';
               if ($dir eq '..') {
                       s#/[^/]+$##;
                       next dir;
               }
               $_ .= '/' . $dir;
               while ($r = readlink) {
                       if ($r =~ m#^/#) { # starts with slash, replace entirely
                               $_ = &Expand($r);
                               s#^/tmp_mnt## && next dir; # dratted automounter
                       } else { # no slash?  Just replace the tail then
                               s#[^/]+$#$r#;
                               $_ = &Expand($_);
                       }
               }
       }
       # lots of /../ could have completely emptied the expansion
       ($_ eq '') ? '/' : $_;
}


-Bennett
[email protected]