使用perl在没有子文件夹的文件夹中搜索特定文件

Search for specific files in folder without subfolders using perl

我想在文件夹中搜索特定文件,但不在该文件夹的子文件夹中。给出以下结构:

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

现在我正在搜索文件夹 A 中的所有 txt 文件,如下所示:

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 }
}

我觉得代码不错,但我总是得到所有 .txt 文件,甚至是子文件夹中的文件。 实际结果是这样的:

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

但我只想要

File3.txt File5.txt

我哪里错了?

你可以使用 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,
);

使用 File::Find::Rule 就简单多了。 (不总是这样吗?)

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 ...
}

您也可以使用 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 ...
   }
}

(请注意,使用 quotemeta(例如,如上所示通过 \Q..\E)不是从 Windows 上的目录名称生成 glob 模式的正确方法。)

获取 c:\Program Files\Windows Defender 目录中所有 .dll 文件的列表

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;
}

输出

  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