use strict; use warnings; $|=1; foreach my $d (@ARGV) { remove_dir($d); rmdir $d; } print "\nDone.\n"; sub remove_dir { my $d = shift; if ( -f $d or -l $d ) { unlink $d; return; } # must be a directory? my (@sfiles, @sdirs); local *DIR; opendir(DIR, $d) || do { print "Can't open $d: $!\n"; return }; foreach (readdir(DIR)) { next if ($_ eq '.'); next if ($_ eq '..'); my $sd = "$d/$_"; if ( -l $sd ) { push(@sfiles, $sd);} elsif ( -d $sd ) { push(@sdirs, $sd); } else { push(@sfiles, $sd); } } closedir(DIR); print "."; # process subdirectories via fork my $count; foreach my $sd (@sdirs) { my $pid; if ($pid = fork()) { # parent ++$count; } elsif (defined $pid) { # child remove_dir($sd); exit; } else { # failure - try again in a bit sleep 5; redo; } while ($count > 2) { wait(); $count--; } } while (wait() != -1) {} #foreach (@sdirs) { # rmdir $_ || do { # warn "$0: Unable to remove directory $_: $!\n"; # }; #} my @cannot = grep {!unlink($_)} @sfiles; if (@cannot) { warn "$0: cannot unlink @cannot\n"; } }