Поиск указанных c файлов в папке без подпапок с использованием perl - PullRequest
1 голос
/ 11 апреля 2020

Я хочу найти указанный c файл в папке, но не во вложенной папке этой папки. Дана следующая структура:

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

Теперь я ищу все текстовые файлы в папке A следующим образом:

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

Где я допустил ошибку?

Ответы [ 2 ]

3 голосов
/ 11 апреля 2020

Вы можете использовать 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 как показано выше) не является правильным способом создания шаблона glob из имени каталога в Windows.)

0 голосов
/ 11 апреля 2020

Получить список всех .dll файлов в каталоге c:\Program Files\Windows Defender

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