Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Help with purging directories and rmdir

Status
Not open for further replies.

Goodeye

MIS
Joined
Nov 11, 2001
Messages
5
Location
US
I have created a perl script which will recursively delete files based on 2 command line arguments. I am attemping to add the ability for this script to clean out empty directories on it's way through also. I have tried using the rmdir command in a couple of variation, but have not been able to get this to work properly. Could someone offer any suggestion on how to correct this script? I would appreciate any ideas.

Code:
#!/usr/bin/perl -w

#######################
#  Script to test functionality
#  before an actual purge is run
#  on a given directory.
#  Live version is named without the
#  word test.
#################################

use File::Find;
my $byteCount=0;
my $fileCount = 0;
my $dateCreated;
my $readable_mtime;
my $searchDir = $ARGV[0]; #read in the passed directory to test existence
my $days_of_purge = $ARGV[1]; # read in the number of days before purging.x

# Convert the days of purge to the correct Unix time.
my $converted_purge_time = $days_of_purge * 86400;  # 86400 = number of seconds in 24 hours

if ( -d $searchDir) {


# Issue the find command passing two arguments
# The first argument is the subroutine that will be called for each file in the path.
# The second argument is the directory to start your search in.

        finddepth(\&cleanup, $ARGV[0]);
        print "$fileCount files are using $byteCount gigabytes\n";


# Subroutine that determines whether we matched the file extensions.

         sub cleanup {
                my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $therest) = stat($_) or die "Unable to stat $_\n";
                my @t = localtime $mtime;
                $date = sprintf "%02u/%02u/%02u %02u:%02u:%02u", $t[4] + 1, $t[3], $t[5] % 100, $t[2], $t[1], $t[0];
                if ((time - $converted_purge_time) > $mtime) {
                                if ( -f ) {
                                        print "$File::Find::name  $date $size\n ";
                                        $byteCount += $size/1024/1024/1024;
                                        $dateCreated= $mtime;
                                        $fileCount++;
                                        unlink("$File::Find::name") or die "Unable to delete $File::Find::name \n";
                                        print $File::Find::dir . "\n";
                                        rmdir $_;
                                }
                }

         }
} else {
        print "Directory does not exist\n";
}
 
The first thing to do is error check the rmdir() function:

Code:
rmdir $_ or die "Unable to rmdir $_: $!\n"

this might help you figure out what the problem is. If you want to remove directory trees you may want to consider File::Path instead of File::Find. Make sure to read the File::Path documentation carefully before using it if you decide to.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
The error check reports this message:

/transcode/tc-video/08-05-2007/sdm.txt 07/07/07 12:00:00 0
/transcode/tc-video/08-05-2007
Unable to remove sdm.txt : No such file or directory


The first line is a print of $File::Find::name and the second is a print of $File::Find::dir.

I have tried the rmdir with both $File::Find::dir and $_. File::Find::Dir reports the error "Unable to stat" the directory name.
 
You have to remove all files and sub folders from a folder before it can be deleted. That is most likely the root cause of your problem.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
In the case of the above error, the only file in that directory was the sdm.txt that I touched with a certain modified stamp to fit in my search pattern. The script removes files older than a certain date which I can pass on the command line. Once it unlinks the last file in the directory, I was expecting the rmdir to then remove the directory. I have folders 07-07-2007 through 08-09-2007 that are not populated but won't delete with this method. As I am using a modified time to search files, I am hesitant to use the rmtree as it can blast good files in an active folder.
 
well, this can't work: rmdir $_;[/]

$_ is the name of the current file, but you said you tried $File::Find::dir which did not work either.

Are you sure the script is deleting the files and the folder is empty?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Does file::find put you in the directory of the file it finds? If so you will need to get out of that directory before you try and rmdir it.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
hmm... good point, and by default File::Find does do a chdir() into each directory. That behavior can be changed with a setting in File::Find:

no_chdir => 1

or something like that.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I think I have solved it. The fact that I was in the current directory and that the Find worked from last to first in the directory list was causing the problem. I took each entry from the $File::Find::dir output and put into an array
Code:
if ( -f ) {
                                        print "$File::Find::name  $date $size\n ";
                                        $byteCount += $size/1024/1024/1024;
                                        $dateCreated= $mtime;
                                        $fileCount++;
                                        unlink("$File::Find::name") or die "Unable to delete $File::Find::name \n";
                                        print $File::Find::dir . "\n";
                                        push (@dirs, $File::Find::dir);
                                }

At the end of the script, I sort the array, chdir to my home, and then rmdir the array

Code:
        # Loop through the directories which reported files and delete them if empty
print "@dirs\n";
@dirs = sort(@dirs);
print "@dirs\n";
chdir;
foreach $dir (@dirs) {
        print "$dir\n";
        rmdir $dir or die "Unable to remove $dir : $! \n";
}


Thanks to everyone for their help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top