【问题标题】:Check if the nested directory structure is empty using perl使用 perl 检查嵌套目录结构是否为空
【发布时间】:2018-02-13 09:07:12
【问题描述】:

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

目录结构如下所示:

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 等,在 level-2 可以有 DIR-X3 or DIR-Y4

我已经编写了一个示例代码,但是如果找到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.

谢谢!

【问题讨论】:

  • 可以澄清一下如何识别“二进制文件” - 是通过扩展名,还是需要进行一些内容检查?
  • @Sobrique:二进制文件可以是 *.h、*.bin 或 *.c 文件。
  • *.h*.c 通常不是“二进制”——它们通常是 ascii 文本预编译。
  • 是的,这是真的。为了简单起见,我将其称为“二进制”。但是在实际用例中,嵌套目录可能有 *.x、*.h 或 *.bin 文件。

标签: perl perl-module


【解决方案1】:

使用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”的文件。

如果您需要执行每个文件测试以检查它们是否为“二进制”,那么您可以在@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 让它变得简单。

【讨论】:

    【解决方案2】:

    我不清楚你的测试用什么二进制文件。我假设在遍历的目录结构中找到的任何文件都是二进制文件。使用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 命令。)传递它@987654327 @ 您可以根据需要使用目录列表调用脚本(可能使用 shell 扩展,如 DIR-*。)

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

    【讨论】:

      【解决方案3】:

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

      #! /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");
      

      【讨论】:

      • 嗨@nakulbansal:在任何一种情况下(无论是否存在二进制文件)我都会收到成功消息。我认为代码需要一些微调。
      【解决方案4】:

      使用(警告:我的)模块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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多