I am writing a Perl application where it would be nice to have a subroutine that could clean up a given pathname such that it does not contain any empty directories.
I have written this subroutine clean_path
, and a wrapper test script:
#! /usr/bin/env perl
use strict;
use warnings;
use Carp;
use File::Basename qw(dirname);
die "Bad arguments!" if @ARGV != 1;
my $path = shift;
clean_path( $path );
exit;
# SYNOPSIS
#
# - clean_path( $path )
#
# ARGUMENTS
#
# - $path
#
# A directory path name. Can be relative to current directory or absolute.
# Examples: 'a/b/c', '/home/user/a/b/c'
#
# Part of $path can be nonexistant, but the part that exists must represent a
# directory.
#
# Example of valid $path:
# 'a/b/c'
# - if 'a/b/c' does not exist, but 'a/b' exists, and is a directory
#
# Example of invalid $path:
# 'a/b/c'
# - if 'a/b/c' does not exist, but 'a/b' exists, and is a filename
#
#
# DESCRIPTION
#
# Removes all *empty* directories at the tail of $path.
# Note: One or more directories at the tail of $path does not have to exist.
#
# ERRORS
#
# croaks if:
#
# - the existant part of $path is not a directory
#
# - you don't have write permissions to a directory.
# Example: $path is '/home/user/a/b/c' and '/home/user' is empty, but
# you do not have write access to directory '/home'
#
sub clean_path {
my ($path) = @_;
while (1) {
if (-d $path) {
if (! -w $path ) {
croak "Cannot clean path '$path': Permission denied.";
}
last unless rmdir $path;
}
elsif (-e $path ) {
croak "Path '$path' is not a directory";
}
# Note: If $path = ".", dirname( $path ) will return "."
# If $path = "/", dirname( $path ) will return "/"
$path = dirname($path);
# cannot remove current directory or root dir
last if $path eq "." or $path eq "/";
}
}