in reply to Cleaning up a path

Well, if you're not worried about portablity:

!/usr/bin/perl use strict; use warnings; my $somepath = "/var/log/../../home/poletti/../../etc/passwd"; my( @true ); foreach( split( /\//, $somepath ) ) { $_ eq ".." ? pop( @true ) : push( @true, $_ ); } print join( '/', @true ), "\n";

Let the golf begin

-derby

Replies are listed 'Best First'.
(golf): Cleaning up a path
by Roy Johnson (Monsignor) on Apr 13, 2005 at 18:29 UTC
    1while s#[^/]+/..(/|$)##
    ikegami's remarks still apply.

    Caution: Contents may have been coded under pressure.

      aye, works great (if you canonise first)

      sub remove_dot_dot_roy_edited { local $_ = $_[0]; $_ = File::Spec::Unix->canonpath($_); 1while s#[^/]+/..(/|$)##; return length($_) ? $_ : '.'; }
Re^2: Cleaning up a path
by ikegami (Patriarch) on Apr 13, 2005 at 17:52 UTC

    While that works for

    /foo/../bar -> /bar foo/../bar -> bar /foo/bar/../../moo -> /moo /var/log/../../home/poletti/../../etc/passwd -> /etc/passwd

    it doesn't work for

    /foo/.. -> <- Should be / foo/.. -> <- Should be . (?) .. -> <- Should be .. ../foo -> foo <- Should be ../foo ../foo/bar -> foo/bar <- Should be ../foo/bar foo/bar/../.. -> <- Should be . (?) /foo/bar/../.. -> <- Should be /
Re^2: Cleaning up a path
by polettix (Vicar) on Apr 13, 2005 at 18:00 UTC
    This breaks in the case depicted by ikegami, but can be adjusted to cope with the portability problem:
    #!/usr/bin/perl use strict; use warnings; use File::Spec; my $somepath = "/var/log/../../home/poletti/../../etc/rc.d"; my @true; $somepath = "/../../../"; # Let's pretend $somepath is a directory... or is it? :) /^\.\./ ? pop( @true ) : push( @true, $_ ) foreach( File::Spec->splitdir($somepath) ); print File::Spec->catdir(@true), "\n";

    Flavio (perl -e "print(scalar(reverse('ti.xittelop@oivalf')))")

    Don't fool yourself.
      /foo/.. -> / <- Fixed /foo/../bar -> /bar <- Still works foo/.. -> <- Should be . (?) foo/../bar -> bar <- Still works .. -> <- Should be .. ../foo -> foo <- Should be ../foo ../foo/bar -> foo/bar <- Should be ../foo/bar foo/bar/../.. -> <- Should be . (?) /foo/bar/../.. -> / <- Fixed /foo/bar/../../moo -> /moo <- Still works {...}/etc/passwd -> /etc/passwd <- Still works
        Correct, but I did not dare asking for some solution which could be valid for relative filenames: this would be some kind of sphere reading!

        Just before you reply (I can hear your breath on my neck!), I want to admit that it also fails miserably with this valid, absolute path:

        /.. -> <- still broken
        I'm understanding proper testing these days...

        Flavio (perl -e "print(scalar(reverse('ti.xittelop@oivalf')))")

        Don't fool yourself.