删除目录的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::Path
和remove_tree
的工作方向与Bash finddepth
相反。
答案 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;