process_files() with the base path as 'path' process_files(): get a list of all files in 'path' for each of the files if it is not a directory and it needs processing process it if it is a directory process_files() with this dir as 'path' #### list_of_all_files = process_files() with the base path as 'path' process_files(): get a list of all files in 'path' for each of the files if it is not a directory process it if necessary add it to our list of files if it is a directory process_files() with this dir as 'path' add the files returned from process_files() to our list of files return our list of files #### process_files ($base_path); # Accepts one argument: the full path to a directory. # Returns: nothing. sub process_files { my $path = shift; # Open the directory. opendir (DIR, $path) or die "Unable to open $path: $!"; # Read in the files. # You will not generally want to process the '.' and '..' files, # so we will use grep() to take them out. # See any basic Unix filesystem tutorial for an explanation of them. my @files = grep { !/^\.{1,2}$/ } readdir (DIR); # Close the directory. closedir (DIR); # At this point you will have a list of filenames # without full paths ('filename' rather than # '/home/count0/filename', for example) # You will probably have a much easier time if you make # sure all of these files include the full path, # so here we will use map() to tack it on. # (note that this could also be chained with the grep # mentioned above, during the readdir() ). @files = map { $path . '/' . $_ } @files; for (@files) { # If the file is a directory if (-d $_) { # Here is where we recurse. # This makes a new call to process_files() # using a new directory we just found. process_files ($_); # If it isn't a directory, lets just do some # processing on it. } else { # Do whatever you want here =) # A common example might be to rename the file. } } } #### process_files ($base_path); # Accepts one argument: the full path to a directory. # Returns: A list of files that reside in that path. sub process_files { my $path = shift; opendir (DIR, $path) or die "Unable to open $path: $!"; # We are just chaining the grep and map from # the previous example. # You'll see this often, so pay attention ;) # This is the same as: # LIST = map(EXP, grep(EXP, readdir())) my @files = # Third: Prepend the full path map { $path . '/' . $_ } # Second: take out '.' and '..' grep { !/^\.{1,2}$/ } # First: get all files readdir (DIR); closedir (DIR); for (@files) { if (-d $_) { # Add all of the new files from this directory # (and its subdirectories, and so on... if any) push @files, process_files ($_); } else { # Do whatever you want here =) .. if anything. } } # NOTE: we're returning the list of files return @files; } #### # Accepts one argument: the full path to a directory. # Returns: A list of files that end in '.html' and have been # modified in less than one day. sub get_new_htmls { my $path = shift; my $ONE_DAY = 86400; # seconds opendir (DIR, $path) or die "Unable to open $path: $!"; my @files = map { $path . '/' . $_ } grep { !/^\.{1,2}$/ } readdir (DIR); # Rather than using a for() loop, we can just # return a directly filtered list. return grep { (/\.html$/) && (time - (stat $_)[9] < $ONE_DAY) && (! -l $_) } map { -d $_ ? get_new_htmls ($_) : $_ } @files; }