$_ = my $original = "/one/two///three/four/..//fourX/five////six/seven"; # you can do job 1 alone like this: tr!/!/!s; print "1: $original -> $_\n"; # OR you can do jobs 1 and 2 together like this; my @srcpaths = split m!/+!, $original; my @outpaths = (); for my $p ( @srcpaths ) { if ( $p eq '..' ) { pop @outpaths; } else { push @outpaths, $p; } } $_ = join( "/", @outpaths ); print "2: $original -> $_\n"; #### pop @outpaths or die "Bad path: $original\n"; #### my @outpath = (); for my $p ( split m!/+!, $original ) { if ( $p eq '..' ) { pop @outpath or die "Bad path: $original"; } else { if ( @outpath ) { my $chk = join "/", @outpath, $p; die "Path not found: $chk" unless ( -d $chk ); } push @outpath, $p; } } my $goodpath = join "/", @outpath;