rsiedl has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks.

I would like to perform the following action:
Given several filename posibilities, check in a linux dir to see if any of these posibilities exist.
The way that i can see to go about it is to do
# readdir() # use regex to match results from readdir()
However the directory can become quite large and i was wondering if there was a more efficient way to achieve this?
Maybe something using
if (-f $filename)
Any help would be appreciated.

Cheers,
Reagen

Replies are listed 'Best First'.
Re: Integrating System commands with regex's
by sh1tn (Priest) on Apr 12, 2005 at 11:05 UTC
    my $regex = { 'txt' => qr{.*txt$}i, 'conf' => qr{.*conf$}i # ... and so on }; opendir DH, '.'; while(my$file=readdir(DH)){ for (keys %$regex){ if ($file =~ /$regex->{$_}/){ print "$file has ", uc$_, " ext\n" } } }


Re: Integrating System commands with regex's
by polettix (Vicar) on Apr 12, 2005 at 12:32 UTC
    The solution provided above by sh1tn is quite general, but from the second section of your question it might be overkill. If I understand well, you actually don't need regexes at all, otherwise I wouldn't understand how you could make the test you propose as the second alternative.

    Regarding the efficiency issue, I think that there shouldn't be much difference between the two approaches; I don't want to Benchmark it because I don't want to fill a directory with useless files :)

    I say that because, on a very general approach, I think that the OS has to load the directory table to give to Perl, and then you end up either analysing it by yourself, or leaving Perl to do it for you, which I don't think makes much difference. If you only want to test if some file exists, I'd stick to the simpler solution, that is:

    my $basedir = "/path/to/directory"; my @candidates = qw ( this and that file ); my @present = grep { -e "$basedir/$_" } @candidates;
    See perldoc -f -X for variants in the test, I've put the most general "file existence" test instead of your more specific "file is a plain file", thus including directories, fifos, etc.

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

    Don't fool yourself.
Re: Integrating System commands with regex's
by jimrobertsiii (Scribe) on Apr 13, 2005 at 06:38 UTC
    You might consider using File::Find. You basically write a "wanted" sub that does all the work on the file to include determining if it is the right file. The "find" method in File::Find will do all the tedious work to include recursing folders.
    use strict; use File::Find; sub wanted{ # $_ is the name of the file in the recursed folder my $filename = $_; # lets only test files that end with .sql return if $filename !~ /^.*\.sql$/; # when called we will be in the recursed folder # so file names can be tested with out the entire path if (-f $filename){ print "Got something called ", $File::Find::name, "\n"; } } find({wanted => \&wanted, no_chdir => 1}, "/home/jroberts");
    Have fun with it.

    -Jim