Perl如何验证路径是目录却不能同时调用opendir()?

时间:2019-04-09 16:24:16

标签: perl find

我正在尝试查找空子目录并将其删除。我敢肯定,有更好的方法可以实现这一目标(我是一个贫穷的程序员,并且在Perl中相对较新),但是即使如此,我还是想了解我的方法有什么问题。

use strict;
use warnings;
use File::Basename; 
use File::Find

my $lambda2 = sub
{
    my $path = $File::Find::name;
    if ( -d $path )
    {
        print("Directory: ", $path, "\n");

        # Define anonymous function to test if directory is empty
        my $hasContent = sub
        {
            my $directory = shift;
            opendir ( my $dh, $directory );
            return scalar ( grep { $_ ne "." && $_ ne ".." } readdir ( $dh ) );
        };
        # Remove item if it is an empty directory
        if ( ! $hasContent->( $path ) )
        {
            rmdir( $path );
        }
    }
};
my $directory = "/Users/username/testdir/";

find( { wanted => $lambda2, no_chdir => 1 }, $directory );

如果testdir有一个名为testsubdir的空子目录,例如,我得到了看似矛盾的响应:

Directory: /Users/username/testdir
Directory: /Users/username/testdir/testsubdir
Can't opendir(/Users/username/testdir/testsubdir): No such file or directory

后一个目录的打印意味着它通过了-d检查,但是随后的错误消息指出没有这样的目录。据我所知,两者之间什么也没有发生。

3 个答案:

答案 0 :(得分:6)

可以这么说,该代码正在删除find脚下的目录。

最简单的解决方法:将postorder traversalfind更改为finddepth,因为

  

它在调用 后调用目录的&wanted函数。

(原始重点)然后,它将不会尝试在刚刚删除的目录上调用wanted

或者,仅收集find中的空目录列表,并在find完成后将其删除。

答案 1 :(得分:4)

让我们抛出一些日志记录语句,看看发生了什么:

my $lambda2 = sub {
    my $path = $File::Find::name;
    if ( -d $path ) {
        print("Directory: ", $path, "\n");
        my $hasContent = sub {
            my $directory = shift;
            opendir ( my $dh, $directory );
            return scalar ( grep { $_ ne "." && $_ ne ".." } readdir ( $dh ) );
        };
        my $hc = $hasContent->($path);
        print STDERR "hc($path) = $hc\n";
        if (! $hc) {
            print STDERR "Deleting $path\n";
            rmdir( $path );
        }
    }
};

$ mkdir -p /Users/username/testdir/testsubdir
$ perl subdir.pl
Directory: /Users/username/testdir
hc(/Users/username/testdir) = 1
Directory: /Users/username/testdir/testsubdir
hc(/Users/username/testdir/testsubdir) = 0
Deleting /Users/username/testdir/testsubdir
Can't opendir(/Users/username/testdir/testsubdir): No such file or directory
 at subdir.pl line 26.

因此,代码或多或少都按设计工作,只是File::Find试图删除后/Users/username/testdir/testsubdir

答案 2 :(得分:0)

使用duawk

列出$target_directory下的所有空目录

 du $target_directory| awk '$1=="0"{print $2}'

删除$target_directory下的所有空目录

 du $target_directory| awk '$1=="0"{system("rmdir "$2);}'