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: bet@sbi.com (Bennett Todd @ Salomon Brothers Inc., NY )
Newsgroups: comp.lang.perl
Subject: Re: Name of file symlink points to?
Message-ID: <910@pivot.sbi.com>
Date: 28 Apr 93 03:54:45 GMT
References: <lsloan.735757842@nova> <lsloan.735829331@nova> <MERLYN.93Apr26102427@kandinsky.intel.com>
Sender: news@pivot.sbi.com
Organization: Salomon Brothers, Inc.
Lines: 56
Nntp-Posting-Host: sandstorm

In article <MERLYN.93Apr26102427@kandinsky.intel.com> merlyn@ora.com (Randal L. Schwartz) writes:
>>>>>> In article <lsloan.735829331@nova>, lsloan@nova.gmi.edu (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
bet@sbi.com


