in reply to Following symlinks manually

It seems pretty straight forward to me, so maybe I'm missing something. readlink returns undef when you point it at a non-link, so...

sub chase_links { my ( $file ) = @_; while ( defined ( my $link = readlink $file ) ) { print "LINK: $file"; $file = $link; } print "NOT LINK: $file"; }

That will list out the links until it gets to a real file. You can insert any logic you like into that loop to short circuit or what-have-you. Is this problem harder than I think?

UPDATE: Oh, I guess it is harder than I thought. The above only works if all links are absolute or relative to the current directory. To work with scattered relative links, you'd have to chdir or track the base directories.

Replies are listed 'Best First'.
Re^2: Following symlinks manually
by Tanktalus (Canon) on Jan 15, 2007 at 22:47 UTC

    Yes, much harder ;-)

    Try this at the shell:

    mkdir a mkdir b ln -s a S ln -s ../b S/S touch b/foo ln -s S/foo foo ln -s S/foo S/foo
    Now, take a look around for a bit. And then try your chase_links on foo.
    perl -e 'my $file = shift; while(defined(my $link = readlink $file)) { + print "LINK: $file\n"; $file = $link; sleep 1; } print "NOT LINK: $f +ile\n"' foo
    Note the sleep in there - I did that to make it easier to kill, 'cuz it's going to go on forever.

    One needs to keep careful track of current directories to figure out where the relative links are actually relative to.

        A cursory glance at File::Spec::Link says it probably will work. I'll go away now to test it. Thanks. I searched CPAN, but coming up with the right search terms is always key!

        (...)

        Yes, that looks right. I think my solution is something like this:

        use File::Spec::Link; my $curlink = shift; my $linkto; while ( ($linkto = readlink($curlink)) and $linkto =~ m:^S/: ) { print "from $curlink "; $curlink = File::Spec::Link->linked($curlink); print "to $curlink\n"; } if (-l $curlink) { # do stuff with readlink($curlink) } else { # do stuff with $curlink (now a file) }
        Thanks!