Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Finding files excluding some

by david.paige (Initiate)
on Mar 30, 2009 at 22:08 UTC ( #754262=perlquestion: print w/replies, xml ) Need Help??
david.paige has asked for the wisdom of the Perl Monks concerning the following question:

I have been reading through the File::Find threads trying to find an answer to this question, but wasn't able to quite find it. I want to write the equivalent of this ksh command in perl:
find /h -depth -type f -name *.[!ao] -print
which should find all files, except those of .a or .o I am willing to redirect them to a file, and then read that into a file. (It was difficult for me to follow the redirections for Find::File.)

I was able to get fully qualified pathnames with File::Find, but wasn't able to exclude certain extensions, and I didn't quite follow some of the redirecting of standard output. If I change the default for standard output, does it revert at some point, or do I have to manually reset it?

What just occurred to me now, is the not completely elegant solution of running a ksh script, doing the file find, and then running the perl program, reading the file list from standard input. Maybe that would be easiest....

Replies are listed 'Best First'.
Re: Finding files excluding some
by ELISHEVA (Prior) on Mar 30, 2009 at 22:16 UTC
    You may prefer File::Finder which is a wrapper around File::Find that mimics the options for the find command.

    If you choose to work directly with File::Find, keep in mind that nearly everything you would normally do on the command line with find you do inside of the visitor function ($wanted in the File::Find documentation). So if you want to exclude things by extension you would do something like this (pseudo code):

    sub doForEachFile { if ($File::Find::name !~ /\.[oa]$/) { #we have what we what ever; } }

    Best, beth

      Very minor syntax preference: If I'm looking to exclude files, I generally return from the 'wanted' function, which just reduces the level of indentation in the subroutine. For example:

      sub doForEachFile { return if $File::Find::name =~ /\.[oa]$/; #we have what we what ever; }

      Does the same thing as your code, just organized a bit differently.

Re: Finding files excluding some
by merlyn (Sage) on Mar 30, 2009 at 23:05 UTC
Re: Finding files excluding some
by Your Mother (Chancellor) on Mar 30, 2009 at 22:47 UTC

    This is only slightly tested but I think it's right-

    use File::Find::Rule; my @files = File::Find::Rule->file() ->not( File::Find::Rule->new->name("*.[!ao]") ) ->in("."); print join("\n", @files), "\n";

    File::Find::Rule. Much easier interface than File::Find (update: fixed backwards names).

    (update: thanks to afoken below; ("*.[!ao]") should not have the bang: ("*.[ao]"), and merlyn's example is probably more in line with what you're after.)

      ->not( File::Find::Rule->new->name("*.[!ao]") )

      I think there should be only one negation. As only *.a and *.o should be ignored, the inner rule should be ...->name('*.[ao]').


      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Finding files excluding some
by Anonymous Monk on Mar 30, 2009 at 23:16 UTC
    Thank you all for the suggestions. I am eager to try them out. I'd played with the Find::File::Rule, but I guess I just needed a little nudge in the right direction.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://754262]
Approved by ELISHEVA
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2017-11-18 13:20 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (277 votes). Check out past polls.