What is the Perl way of removing a directory and then all empty parent directories up to the first non-empty one? In other words, what could one use instead of:
system 'rmdir', '-p', $directory;
which, in starting with d
, would first remove d
and then c
, and then b
, but not a
, since a
would still contain x
, like this:
a
a/b
a/b/c
a/b/c/d
a/x
resulting in
a
a/x
It's not the built-in rmdir
, as it can only remove a single directory. (doc)
It's not finddepth ( sub {rmdir}, '.' )
, using File::Find
, as it removes children, not parents. (doc)
It's not the remove_tree
function of the File::Path
module either, since it not only removes children directories but files as well. (doc)
Notice, remove_tree
and finddepth
work in the opposite direction of Bash rmdir --parent
.
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;
}
Notes:
Efficient. By checking the result of rmdir
instead of using ->children
or ->iterator
, this solution is avoids needless calls to readdir
.
No race conditions. Unlike the solutions that use readdir
(via ->children
or ->iterator
), this solution doesn't suffer from a race condition.
This solution also avoids the redundant -d
check used by an earlier solution.
This solution, unlike those before it, will handle a tree that's empty except for the directories to remove.