How do you get the first existing ancestor directory given a file path?
In Perl, if given a file path, how do you find the first existing ancestor?
For example:
- If given the path
/opt/var/DOES/NOT/EXIST/wtv/blarg.txt
and directory/opt/var/DOES/
is not present but directory/opt/var/
is, the result should be/opt/var/
. - If given the path
/home/leguri/images/nsfw/lena-full.jpg
and directory/home/leguri/images/nsfw/
does not exist, but directory/home/leguri/images/
does, the result should be/home/leguri/images/
.
Is there a module or function which does this, or is it just a matter of splitting the path on /
and testing fo开发者_开发问答r existence?
The closest I know of is Path::Class, which doesn't do exactly what you want but may save you a couple of steps in splitting the path.
use Path::Class 'dir';
sub get_existing_dir {
my ( $path ) = @_;
my $dir = dir( $path );
while (!-d $dir) {
$dir = $dir->parent;
}
return $dir->stringify;
}
my $file = '/opt/var/DOES/NOT/EXIST/wtv/blarg.txt';
my $dir = get_existing_dir( $file );
print $dir;
Monkey patch it
#!/usr/bin/perl --
use strict;
use warnings;
use Path::Class ;
my @paths = map dir($_) ,
map join( '/', $_, 1..6 ),
grep defined,
@ENV{qw/ WINDIR PROGRAMFILES TEMP HOME /},
'Q:/bogus/drive/and/path',
'QQ:/bogus/drive/bogusly/treated/as/file',
;
push @paths, dir('bogus/relative/path/becomes/dot');
push @paths, dir('bogus/relative/path/becomes/relative/to/cwd')->absolute;
for my $path ( @paths ) {
print $path, "\n\t=> ", $path->real_parent, "\n\n";
}
sub Path::Class::Entity::real_parent {
package Path::Class::Entity;
my( $dir ) = @_;
while( !-d $dir ){
my $parent = $dir->parent;
last if $parent eq $dir ; # no infinite loop on bogus drive
$dir = $parent;
}
return $dir if -d $dir;
return;
}
__END__
C:\WINDOWS\1\2\3\4\5\6
=> C:\WINDOWS
C:\PROGRA~1\1\2\3\4\5\6
=> C:\PROGRA~1
C:\DOCUME~1\bogey\LOCALS~1\Temp\1\2\3\4\5\6
=> C:\DOCUME~1\bogey\LOCALS~1\Temp
C:\DOCUME~1\bogey\1\2\3\4\5\6
=> C:\DOCUME~1\bogey
Q:\bogus\drive\and\path\1\2\3\4\5\6
=>
QQ:\bogus\drive\bogusly\treated\as\file\1\2\3\4\5\6
=> .
bogus\relative\path\becomes\dot
=> .
C:\temp\bogus\relative\path\becomes\relative\to\cwd
=> C:\temp
精彩评论