使用 perl 检查嵌套目录结构是否为空

Check if the nested directory structure is empty using perl

我的要求是检查嵌套目录结构是否包含任何二进制文件。

目录结构如下所示:

DIR-A
    |
    |--DIR-X
    |       |
    |       |--DIR-X1
    |       |--DIR-X2
    |
    |--DIR-Y
    |       |
    |       |--DIR-Y1
    |       |--DIR-Y2
    |       |--DIR-Y3
    |
    |--DIR-Z
    |       |
    |       |--DIR-Z1
    |       |--DIR-Z2
    |       |--DIR-Z3

在任何时间点,Level-1 或 Level-2 都可以有更多目录,即在 level-1 可以有更多目录,即 DIR-P, DIR-Q 等,并且可以有 DIR-X3 or DIR-Y4在 2 级。

我写了一个示例代码,但是如果它找到 DIR-X1,它就会退出,理想情况下,如果目录中有一个二进制文件,它应该退出。

#!/usr/bin/perl

my $someDir = "/path/of/DIR-A";
my @files = ();
my $file;
my $i=0;

opendir(DIR, "$someDir") or die "Cant open $someDir: $!\n";
    @files = readdir(DIR);
    foreach $file(@files) 
    {
          unless ($file =~ /^[.][.]?\z/) 
        {
            print "$i : $file \n";              
            $i++;
            last;
            }
        }

    if ($i != 0) 
    {
        print "The directory contains files! \n";
        exit 1;      
    } 
    else 
    {
        print "This DIR-A is Empty! \n";
        exit 0;
    }

closedir(DIR);

请建议我获得如下预期的解决方案:

read DIR-A
print SUCCESS, if none of the nested directories have a binary file.
print ERROR, if at least one of the nested directories has a binary file.

谢谢!

使用File::Find::Rule

#!/usr/bin/env perl
use strict;
use warnings;

use File::Find::Rule;

my $someDir = "/path/of/DIR-A";

my @files = File::Find::Rule->file()
                            ->name('*.bin')
                            ->in($someDir);

这将为您提供扩展名为“.bin”的所有文件。

如果您需要执行每个文件测试以检查它们是否 'binary',那么您可以在 @files 列表中使用 grep

my @files = grep {-B} File::Find::Rule->file()
                                      ->in($someDir);

print "Binary files found\n" if @files;

另外:

  • use strict;use warnings;。不错。
  • 代码格式化真是个好东西。 perltidy -pbp 让一切变得简单。

您可以使用以下脚本递归地查找二进制文件是否存在。

#! /usr/bin/env perl
use warnings;
use strict;
use File::Find;

my $path="/path/of/DIR-A";

sub find_binary {
    my $file = $File::Find::name;

    if (-B $file && ! -d $file) {
        print "ERROR: At least one of the nested directories has a binary file : $file\n";
        exit;
    }
}

find(\&find_binary,$path);
print("SUCCESS: None of the nested directories have a binary file. \n");

使用(警告:我的)模块 File::Globstar:

use v5.10;
use File::Globstar qw(globstar);

my $dir = $ARGV[0] // '.';
say join "\n", grep { -B && ! -d } globstar "$dir/**";

如果您想要列表中的文件列表,请分配它而不是打印它:

my @nondirs = grep { -B && ! -d } globstar "$dir/**";

如果你知道文件的扩展名,你也可以这样做:

my @nondirs = grep { -B && ! -d } globstar "$dir/**/*.png";

请注意,文件测试 -B 为空文件生成了一个真值,这可能不是您想要的。在这种情况下,将测试更改为 -B && -s && ! -d.

我不清楚你的测试用的是什么二进制文件。我假设在遍历的目录结构中找到的任何文件都是二进制文件。使用File::Find,这是一个核心模块:

use File::Find;

my $error = 0;
find(\&wanted, @ARGV);

if( $error ) {
  print "ERROR, $error files found\n";
}
else {
  print "SUCCESS\n";
}

sub wanted {
  if( -f $_ ) {
    $error++;
  }
}

您可以向 wanted 函数添加任何测试。 find 函数将调用为在也传递的目录列表中找到的每个文件提供的函数,这些文件将按深度优先搜索顺序递归遍历(很像 find 命令)。传递它 @ARGV 您可以根据需要使用目录列表调用脚本(可能使用 shell 扩展,如 DIR-*。)

测试函数会在$_中获取正在遍历的文件名,而当前工作目录设置为包含该文件的目录。