Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Deleting folders based on name.

by fazedandconfused (Novice)
on Oct 18, 2010 at 15:25 UTC ( #865965=perlquestion: print w/replies, xml ) Need Help??
fazedandconfused has asked for the wisdom of the Perl Monks concerning the following question:


I'm fairly new to perl and have a requirement to create a script but I'm struggling a bit.

I have a directory on a Windows server which has 2 levels of subfolders below it. I want to read in the first list of subfolders and then for each of those read in the next level down. Once I have these (they are named MMYY) I want to work out any that are over 3 months old but based on the folder name and not any modification date then delete the older ones.

I've got this piece of code that should get me the first subfolder level,

my @HighFolders; my $Highpath="D:/FSA/Recordings/"; use File::Util; my($hf) = File::Util->;new(); my(@HighFolders) = $hf->;list_dir($Highpath,'--dirs-only');

then I have the following that should get me the next level down,
foreach $lf(@Highfolders) use File::Util; my($lf) = File::Util->;new(); my(@Lowfolders) = $lf->;list_dir($lf,'--dirs-only); }

What I'm wondering is how I would go about making the @Lowfolders array uniquely named for each $Highfolder.

I also will need to convert the MMYY Lowfolder name to a Date at some point so that I can compare to the current date and work out which folders are more than 3 months old so that I can build my list of folders to delete.

Any help anyone can give me would be very much appreciated.
Thanks, Neil.

Replies are listed 'Best First'.
Re: Deleting folders based on name.
by Marshall (Abbot) on Oct 18, 2010 at 15:39 UTC
    Why don't you just concatenate "$hifolder/$lowfolder"? That is unique and gives you the absolute path that you would wind up using to delete the directory anyway. You probably need to prepend $hipath to the $highfolder name perhaps in the loop that iterates over the $highfolders".

    my @FullDirPaths = map{"$hipath/$highfolder/$_"}@LowFolders;

    You might want to look at Date::Time module for comparing dates. Or you could make a little YYYYMM "date math" routine yourself, but I suspect that using the module will be easier.

    Don't know if this is a typo or not, but don't put a ";" after the "->" ie have "->new();"

    Update: Don't know where my brain is this morning...Actually I don't think that you need to save the @FullDirPaths like above at all. At this point in the code you have all 3 parts of the full path: "$hipath/$highfolder/$lowfolder". Just decide right there whether or not you should delete this particular $lowfolder or not! No need to save the names to process later. You can use a simple regex to separate out the month and year from the filename like shown below...

    my @dates = ( '1010', '1007'); foreach my $date (@dates) { my ($year,$mon) = $date =~ m/\d\d/g; print "year = $year month= $mon\n"; }
Re: Deleting folders based on name.
by halfcountplus (Hermit) on Oct 18, 2010 at 15:54 UTC

    I presume there are some typos here with the superfluous colons:

    my($hf) = File::Util->;new(); my(@HighFolders) = $hf->;list_dir($Highpath,'--dirs-only');

    If I follow you properly, you might want to make one single datastructure here -- each element of the "Highfolders" array would be an array reference. The first element of that array (0) would be the MMYY name, the second element (1) would be another array reference to an array containing the subfolders. I think this would eliminate the need for unique names (unless there is some further reason for that). Might look something like:

    #!/usr/bin/perl -w use strict; use File::Util; my $hf = File::Util->new(); my $path = '/'; my @Folders; foreach ($hf->list_dir($path,'--dirs-only')) { my @tmp = $_; push @Folders, \@tmp; # the outer array ref } foreach (@Folders) { my $lf = File::Util->new(); my @tmp = $lf->list_dir($path.$_->[0],'--dirs-only'); $_->[1] = \@tmp; # inner array ref } # verify: foreach (@Folders) { print $_->[0]."\n"; foreach my $sub (@{$_->[1]}) { print "\t$sub\n"; } }

    I haven't used File::Util before so I inferred from your code, but I did test this -- I hope that's kinda what you are looking for. It's nice to comment on datastructures like this in the code, eg:

    my @Folders; # array of array refs, each sub-array = # 0: directory name # 1: array of subdirectories
Re: Deleting folders based on name.
by fazedandconfused (Novice) on Oct 21, 2010 at 08:54 UTC
    Thanks for the replies.

    As I couldn't access PerlMonks yesterday I ended up finding a completely different way of doing it.

    #!/usr/local/bin/perl use warnings; use strict; use File::Find::Rule; use Date::Calc qw(Delta_Days); use File::Path qw(remove_tree); my $path="D:/FSA/Recordings/"; my @folders = File::Find::Rule->directory->in( $path ); foreach my $i (@folders){ if ($i =~ /[0-9]{4}/) { my $folder = substr($i,-4,4); my $month = substr($folder,0,2); my $year = substr($folder,2,2); my $folderyear = "1" . $year; my @folderdate = ($folderyear, $month, 01); my($curday, $curmonth, $curyear) = (localtime)[3,4,5]; my @curdate = ($curyear, $curmonth + 1, $curday); my $difference = Delta_Days(@folderdate, @curdate); if ($difference > 93) {remove_tree $i;} }; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://865965]
Approved by Marshall
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2017-05-29 23:46 GMT
Find Nodes?
    Voting Booth?