如何使用Perl删除目录及其空祖先?

时间:2017-04-13 20:18:58

标签: perl rmdir

删除目录的Perl方法是什么,然后所有 目录直到第一个非空目录?换句话说,可以使用什么而不是:

system 'rmdir', '-p', $directory;

,从d开始,首先删除d然后c,然后b,而不是a,因为{{1}仍然会包含a,如下所示:

x

导致

a
a/b
a/b/c
a/b/c/d
a/x

这不是内置的a a/x ,因为它只能删除单个目录。 (doc

使用rmdir不是finddepth ( sub {rmdir}, '.' ),因为它会删除子项,而不是父项。 (doc

这不是File::Find模块的remove_tree功能,因为它不仅会删除子目录,还会删除文件。 (doc

请注意,File::Pathremove_tree的工作方向与Bash finddepth相反。

3 个答案:

答案 0 :(得分:5)

use Path::Tiny qw( path );

my $p = path('a/b/c/d');

while (!$p->is_rootdir()) {
    if (!rmdir($p)) {
        last if $!{ENOTEMPTY};
        die("Can't remove \"$p\": $!\n");
    }

    $p = $p->parent;
}

注意:

  • 高效。通过检查rmdir的结果,而不是使用->children->iterator,此解决方案可以避免对readdir进行不必要的调用。

  • 没有竞争条件。与使用readdir(通过->children->iterator)的解决方案不同,此解决方案不会遇到竞争条件。

  • 此解决方案还避免了早期解决方案使用的冗余-d检查。

  • 此解决方案与之前的解决方案不同,它将处理一个空的树,除了要删除的目录。

答案 1 :(得分:3)

与往常一样,使用我最喜欢的Path::Tiny

use 5.014;
use warnings;
use Path::Tiny;
use autodie;

my $p = path('a/b/c/d');     # starting
die "$p is not a dir" unless -d $p;

while( ! $p->children ) {    # if it is empty
        rmdir $p;            # remove it
        $p = $p->parent;     # go upward
}

答案 2 :(得分:3)

AFAIK这并不存在。您可以使用Path::Tiny轻松自己编写。它是一个简单的递归函数。

#!/usr/bin/env perl

use strict;
use warnings;
use v5.10;

use Carp;
use Path::Tiny;
use autodie;

sub Path::Tiny::rmdir_if_empty {
    my $self = shift;

    # Stop when we reach the parent.
    # You can't rmdir('.') anyway.
    return if $self eq '.';

    croak "$self is not a directory" if !$self->is_dir;

    # Stop if the directory contains anything.
    # I use an iterator to avoid a possibly very long list.
    my $iter = $self->iterator;
    return if defined $iter->();

    # rmdir will not delete a non-empty directory, a second safeguard
    rmdir $self;

    return $self->parent->rmdir_if_empty;
}

path("a/b/c/d")->rmdir_if_empty;