So;
I have a list in a text file that contains sections of a what would be filenames..

I'm wanting to read from this text file into I guess an array, unless there's a better way to do it.. and then find the file that matches with each of the entries in the array and perform an action against that file....

Text file
aaa.exe
bbb.exe
ccc.exe
ddd.exe

File list
aaa.exe
ggg.exe
ccc.exe
rrr.exe

So how would I read in the entries of the text file, read in the entries of the *.exe files in a specified directory.. search the *.exe's for matches and then perform an action against them?

Dani AI

Generated

A robust, fast pattern is to read the list of wanted names once into a lookup (hash) and then scan the target directory a single time. This avoids nested loops and the common bug seen in ’s first attempt where the list file is read from inside the directory loop (the filehandle is exhausted the first time). It also follows good file-handle practice (three-arg open, lexical handles) and handles Windows CRLFs.

use strict;
use warnings;
use File::Spec;

my $dir   = 'C:\\testingdir';
my $list  = 'C:\\testingdir\\testing.txt';

open my $lh, '<', $list or die "Can't open '$list': $!";
my %want;
while (my $line = <$lh>) {
    chomp $line;
    $line =~ s/\r$//;        # strip CR if file was edited on Windows
    next unless length $line;
    $want{lc $line} = 1;     # canonicalize for case-insensitive comparison
}
close $lh;

opendir my $dh, $dir or die "opendir '$dir': $!";
while (my $file = readdir $dh) {
    next if $file eq '.' || $file eq '..';
    next unless $file =~ /\.exe$/i;   # restrict to .exe if desired
    if ($want{lc $file}) {
        my $path = File::Spec->catfile($dir, $file);
        print "***FOUND*** $path\n";
        # perform action on $path here
    }
}
closedir $dh;

Notes and edge cases:

  • For simple existence checks on a known directory, testing -f File::Spec->catfile($dir, $name) (as suggested by ) is even simpler when the list contains only basenames.
  • If the list may contain full paths or mixed data, normalize with File::Basename::basename before comparing.
  • Avoid regex matching unless intentional: string equality (lc + eq) prevents accidental partial matches and removes the need for quotemeta.
  • For very large lists or directories, a hash lookup is O(1) per file and far faster than nested loops; for enormous datasets consider on-disk DB (DB_File) or streaming approaches.

Recommended Answers

All 4 Replies

This is what I've come up with so far :-/

my $directory = 'C:\testingdir';

opendir(DIR,$directory);
open (REMAINING, 'C:\testingdir\testing.txt');
my $remaining_patch_names;
my @files = readdir(DIR);
foreach my $name (@files)
{
  while ($remaining_patch_names = <REMAINING>)
       {
            chomp($remaining_patch_names); #remove new-line character from end of $remaining_patch_names
            my $qmname = quotemeta($remaining_patch_names);
            if ($name =~m/$qmname/i)
            {
                print "***FOUND*** $name \n";
            }
            else
            {
                print "***NOTFOUND*** $name \n";
            }
       }
       
}

This seems to be working.. but is there a better way?

my $directory = 'C:\testing';
opendir(DIR,$directory);
open (REMAINING, 'C:\testing\testing.txt');
my $remaining_patch_names;
my @files = readdir(DIR);
my @patches = <REMAINING>;
foreach my $patch (@patches)
{
 chomp($patch);
 foreach my $name (@files)
 {
  chomp($name);
  if ($patch =~m/$name/i)
            {
                print "***FOUND*** $patch \n";
                last;
            }
            else
            {
                
            }
 }
        
}
#!/usr/bin/perl
#CheckFilesExist.pl
use 5.006;
use strict;
use warnings;
my $directory = '/home/david/Documents';
open (my $fh, '<', 'files.txt');
while (<$fh>) {
	chomp;
	if (-e $directory . '/' . $_) {
		print "***FOUND*** $_ \n";
	}
	else {
		print "***NOTFOUND*** $_ \n";
	}
}

The following incorporates a couple of improvements on the above, including open (my $fh, '<', $filenames) or die "Could not open $filenames $!";

#!/usr/bin/perl
#CheckFilesExist.pl
use 5.006;
use strict;
use warnings;
my $cur_dir = '/users/david/Programming/Perl';
my $dir2check = '/users/david/Documents';
my $filenames = "$cur_dir/files.txt";
open (my $fh, '<', $filenames) or die "Could not open $filenames $!";
while (<$fh>) {
	chomp;
	if (-e $dir2check . '/' . $_) {
		print "***FOUND*** $_ \n";
	}
	else {
		print "***NOTFOUND*** $_ \n";
	}
}
close($fh);
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.