#!/usr/bin/env perl # realdirs - filter colon-separated lists in $*, producing a single list # with only real directories or relative ones, removing duplicates # leaves the empty component! # does NOT include symbolic links to directories # # useful in .login scripts when setting vars such as $PATH and $MANPATH # usage: setenv PATH `realdirs $PATH` # # $Id$ # # author: Reinier use warnings; use strict; #use Cwd qw(realpath); # the Cwd of pre-5.6 perl doesn't know this use Cwd qw(fast_abs_path); my @args = split( /:/, join( ':', @ARGV, 'junk' ) ); pop(@args); # to deal with : at end, which is swallowed by split (Perl bug?) my %shortest_path_for; # maps resolved paths to shortest paths my %seqno; # maps resolved paths to index in $PATH my $seqno = 0; foreach my $givenpath (@args) { if ( $givenpath eq '' || $givenpath =~ m#^[./]+$# ) { # empty or relative component, use as is $shortest_path_for{$givenpath} = $givenpath; $seqno{$givenpath} = ++$seqno; next; } # if not, normalise the path, then pick the shortest path normalizing # to the same value so far #my $realpath = realpath($givenpath); # 5.005 Cwd doesn't know this my $realpath = eval { fast_abs_path($givenpath) }; if ( !defined $realpath ) { # the path wasn't found on the file system next; } if ( $realpath =~ m#^[./]+$# ) { # absolute is now relative, use absolute $realpath = $givenpath; } if ( !defined( $shortest_path_for{$realpath} ) ) { # pick the shorter one and use it my $shortestpath = length($givenpath) < length($realpath) ? $givenpath : $realpath; $shortest_path_for{$realpath} = $shortestpath; $seqno{$realpath} = ++$seqno; } elsif ( length( $shortest_path_for{$realpath} ) > length($givenpath) ) { # a new, shorter equivalent for this $realpath has been found - use it $shortest_path_for{$realpath} = $givenpath; } # otherwise, we already have a better eq. for $givenpath, so just ignore it } print join( ':', map { $shortest_path_for{$_} } sort { $seqno{$a} <=> $seqno{$b} } keys %seqno ), "\n";