digestBen
digestBen

Reputation: 77

Search for specific files in folder without subfolders using perl

i want to search for specific file inside a Folder but not in the subfolder of this folder. Following Structure is given:

FolderA
|
|__SubFolder1
    |__File1.txt
    |__File2.txt
|
|__File3.txt
|__File4.cmd
|__File5.txt

Now i am searching all txt files in Folder A like this:

sub GetFiles()
{
  my @DIRS = (FolderA);
  find ( \&searchFiles, @DIRS );
  for my $myfile (%MYFILES) {
    ####do something with the files###
  }
}

sub searchFiles() 
{
  return unless /\.txt/;
  return unless -f $File::Find::name;

  $MYFILES{$File::Find::name} = {'NAME'=> $File::Find::name }
}

The Code looks good to me but I always get all .txt Files, even those from Subfolder. Actual result is like this:

File1.txt File2.txt File3.txt File5.txt

But I want only

File3.txt File5.txt

Where did I the mistake?

Upvotes: 1

Views: 702

Answers (2)

ikegami
ikegami

Reputation: 385657

You could use File::Find.

use File::Find qw( find );

my @dir_qfns = qw( FolderA );

find(
   sub {
      # Don't do anything for a base dir.
      return if $_ eq '.';

      # Don't recurse.
      $File::Find::prune = 1;

      stat($_) 
         or do {
            warn("Skipping \"$_\": Can't stat: $!\n");
            next;
         };

      -f _
         or return;
      /\.txt\z/
         or return;

      # ... do something with $File::Find::name/$_ ...
   },
   @dir_qfns,
);

It's far simpler with File::Find::Rule. (Isn't it always?)

use File::Find::Rule qw( );

my @dir_qfns = qw( FolderA );

for my $qfn (
   File::Find::Rule
   ->mindepth(1)
   ->maxdepth(1)
   ->file
   ->name("*.txt")
   ->in(@dir_qfns)
) {
   # ... do something with $qfn ...
}

You could also do it using glob.

my @dir_qfns = qw( FolderA );

for my $dir_qfn (@dir_qfns) {
   for my $fn (glob("\Q$dir_qfn\E/*.txt")) {
      my $qfn = "$dir_qfn/$fn";
      stat($qfn) 
         or do {
            warn("Skipping \"$qfn\": Can't stat: $!\n");
            next;
         };

      -f _
         or next;

      # ... do something with $fn/$qfn ...
   }
}

(Note that using quotemeta (e.g. via \Q..\E as shown above) is not a proper way of generating a glob pattern from a directory name on Windows.)

Upvotes: 4

Polar Bear
Polar Bear

Reputation: 6798

Get list of all .dll files in c:\Program Files\Windows Defender directory

use strict;
use warnings;
use feature 'say';

my $dir_defend = 'c:\Program Files\Windows Defender';
my $files_dll  = getFileList($dir_defend,'dll');

say '
  File list
-------------------------';
say for @{ $files_dll };

sub getFileList {
    my $dir = shift;
    my $ext = shift;

    opendir my $dh, $dir
        or die "Can't opendir $dir";

    my @files = grep { /\.${ext}$/ && -f "$dir/$_" } readdir($dh);

    close $dh;

    return \@files;
}

Output

  File list
-------------------------
AMMonitoringProvider.dll
DefenderCSP.dll
EppManifest.dll
MpAsDesc.dll
MpAzSubmit.dll
MpClient.dll
MpCommu.dll
MpEvMsg.dll
MpOAV.dll
MpProvider.dll
MpRtp.dll
MpSvc.dll
MsMpCom.dll
MsMpLics.dll
MsMpRes.dll
ProtectionManagement.dll
shellext.dll

Upvotes: -1

Related Questions