Exercise for Chapter 7 of "Intermediate Perl"
########################################################################## Brief: Exercise for Chapter 7 of "Intermediate Perl"# File: ch7_exam.pl# Creator: thinkhy# Date: 12/23/2012#########################################################################use File::use Time::use File::Spec::qw(canonpath no_upwards)my $target_dow = 2# Sunday is 0, Monday is 1, ...my @starting_directories = ".""e:/tmp"my $seconds_per_day = 24 * 60 * 60my$sec$min$hour$day$mon$yr$dow= localtimemy $start = 000$day$mon$yr# midnight todaywhile $dow != $target_dow # Back up one day$start -= $seconds_per_day# hope no DST! :?)if --$dow < 0 $dow += 7my $stop = $start + $seconds_per_daymy$gather$yield= $start$stop$gather@starting_directoriesmy @files = $yield->for my $file @files my $mtime = stat $file9# mtime via slicemy $when = localtime $mtime print "$when: $file\n"sub gather_mtime_between my $start_time = shift my $end_time = shiftmy @files =########################################################################## Here use canonpath, details explained as below# canonpath:# No physical check on the filesystem, but a logical cleanup of a path.# no_upwards:# Given a list of file names, strip out those that refer to a# parent directory. (Does not strip symlinks,# only '.', '..', and equivalents.)# Refer to http://perldoc.perl.org/File/Spec.html## Also, notice that when using stat inside the callback, the filename is $_# but when the filename reperting to the user, the name is $File::Find::name# because different current working directory for callback and user function#########################################################################sub my $when = stat $_9 push @files$File::Find::name if $when >= $start_time and $when <= $end_time sub @files = @files wantarray @files @files# Here is the 'official' answer for Chapter 7sub gather_mtime_between my$begin$end= @_ my @filesmy $gatherer = sub my $timestamp = stat $_9 unless defined $timestamp warn "Can't stat $File::Find::name: $!, skipping\n" return push @files$File::Find::nameif $timestamp >= $begin and $timestamp <= $endmy $fetcher = sub @files $gatherer$fetcher############################################################################# Compared with answer, I omitted a special condition that the timestamp# will be undef if the stat fails for some reason. That can happen, for example,# if it finds a dangling symbolic link(the target file doesn't exist).# In that case, the callback warns the user and returns early.# With the code of answer, if we omit that check, we can get warnings of # an undefined value during the comparison with begin time and end time.############################################################################