简体   繁体   中英

How to find files/folders recursively in Perl script?

I have a perl script which I have written to search files present in my windows folders, recursively. I enter the search text as the perl script runtime argument to find a file having this text in it's name. The perl script is as below:

use Cwd;

$file1 = @ARGV[0];    

#@res1 = glob "*test*";
#@res1 = glob "$file1*";
@res1 = map { Cwd::abs_path($_) } glob "$file1*";
foreach (@res1)
{
    print "$_\n";
}

But this is not searching all the sub-directories recursively. I know glob doesn't match recursively.
So tried using module File::Find and the function find(\\&wanted, @directories);

But I got a error saying find() undefined. From what I read from help, I thought find() function is defined by default in Perl installation, with some basic code to find folders/files. Isn't it correct?

Questions is, in the above perl script, how do I search for files/folders recursively?

Second questions, I found that perldoc <module> help does not have examples about using a certain function in that module, which would make it clear.

Can you point to some good help/document/book for using various perl functions from different perl modules with clear examples of usage of those module functions.

Another excellent module to use is File::Find::Rule which hides some of the complexity of File::Find while exposing the same rich functionality.

use File::Find::Rule;
use Cwd;

my $cwd = getcwd();
my $filelist;

sub buildFileIndex {
    open ($filelist, ">", "filelist.txt") || die $!;

    # File find rule
    my $excludeDirs = File::Find::Rule->directory
                              ->name('demo', 'test', 'sample', '3rdParty') # Provide specific list of directories to *not* scan
                              ->prune          # don't go into it
                              ->discard;       # don't report it

    my $includeFiles = File::Find::Rule->file
                             ->name('*.txt', '*.csv'); # search by file extensions

    my @files = File::Find::Rule->or( $excludeDirs, $includeFiles )
                                ->in($cwd);

    print $filelist map { "$_\n" } @files;
    return \$filelist;
}

These two pages are all you need to study:

An alternative would be to use find2perl to create the start of the script for you. It can turn a find command like,

find . -type f -name "*test*" -print

To an equivalent perl script. You just put find2perl instead of find. It uses File::Find under the hood but gets you going quickly.

If you don't mind using cpan module, Path::Class can do the work for you:

use Path::Class;

my @files;
dir('.')->recurse(callback => sub {
    my $file = shift;
    if($file =~ /some text/) {
        push @files, $file->absolute->stringify;
    }
});

for my $file (@files) {
    # ...
}
use 5.010; # Enable 'say' feature
use strict;
use warnings;

use File::Find; # The module for 'find'

find(\&wanted, @ARGV); # @ARGV is the array of directories to find.

sub wanted {
  # Do something...

  # Some useful variables:
  say $_; # File name in each directory
  say $File::Find::dir; # the current directory name
  say $File::Find::name; # the complete pathname to the file
}

Example for listing driver modules on Linux (Fedora):

use 5.022;
use strict;
use warnings;

use POSIX qw(uname);
use File::Find;

my $kernel_ver = (uname())[2];
my @dir = (
  "/lib/modules/$kernel_ver/kernel/drivers"
);

find(\&wanted, @dir);

sub wanted {
  say if /.*\.ko\.xz/;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM