Apurva Choudhary
Apurva Choudhary

Reputation: 55

Multiple File search in varying level of directories in perl

I have a directory structures as follows. I want to have only the first path, not the paths which are present after the first file in the report. I also don't want to check further in that report after getting first file, thus want to save time.

structure for directory:

Report 1
A--B--C--D--E--abc.txt--->needed this 
A--B--C--D--E--F--abc.txt avoid this
Report 2
A--B--C--D--E--Q--R--abc.txt needed this, as it is single in its report.
Report 3
A--H--I--J--abc.txt --needed this
Report 4
A--B--C--D--M--abc.txt needed this
A--B--C--D--M--N--abc.txt avoid this
.
.
.
.

millions of such reports.

Directory A contains millions of reports. Each report contains multiple files and subdirectories. Each report have abc.txt in one of the path present and same path post abc.txt level ,may contain other subdirectories inside the path which also have have abc.txt.

Note: Reports are of varying level of subdirectories

     

open my $fh, '-|', 'find', $maindirectory, '-type','d' or die "cant open pipes $! \n";
                while (<$fh>) {
                    my $dirpath = $_;
                    chomp $dirpath;
                    if(-d $dirpath) {
                        $filewithpath = File::Spec->catfile( $dirpath, "abc.txt" );
                        if (-e $filewithpath) {
                            push @patharray, $filewithpath;
                        }
                    }
                }

Upvotes: 1

Views: 220

Answers (1)

pii_ke
pii_ke

Reputation: 2891

I think you want the abc.txt files which are nearest to the main directory for a common initial path. That is, you want to avoid looking for A/B/C/../F/abc.txt if A/B/C/abc.txt has been found.

This criteria will select files A/H/I/J/abc.txt, A/B/C/D/M/abc.txt, A/B/C/D/E/abc.txt for your sample directory tree. And not A/B/C/D/E/Q/R/abc.txt, which you have marked as needed in your sample, because the file A/B/C/D/E/abc.txt has already been found above it in the directory hierarchy.

You can do this in perl using:

use strict;
use warnings;

use File::Find;
my $maindirectory = "A";
#replace with actual main directory name

File::Find::find(
    sub {
        if ( -d && -f "$_/abc.txt" ) {
            $File::Find::prune = 1;
            process_path_of_needed_file("$File::Find::name/abc.txt");
        }
    },
    $maindirectory
);

See https://perldoc.perl.org/File/Find.html

Upvotes: 2

Related Questions