Last active
December 10, 2015 01:48
-
-
Save thinkhy/4361976 to your computer and use it in GitHub Desktop.
Exercise for Chapter 7 of "Intermediate Perl"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
######################################################################### | |
# Brief: Exercise for Chapter 7 of "Intermediate Perl" | |
# File: ch7_exam.pl | |
# Creator: thinkhy | |
# Date: 12/23/2012 | |
######################################################################### | |
use File::Find; | |
use Time::Local; | |
use File::Spec::Functions 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 * 60; | |
my($sec, $min, $hour, $day, $mon, $yr, $dow) = localtime; | |
my $start = timelocal(0, 0, 0, $day, $mon, $yr); # midnight today | |
while ($dow != $target_dow) { | |
# Back up one day | |
$start -= $seconds_per_day; # hope no DST! :?) | |
if (--$dow < 0) { | |
$dow += 7; | |
} | |
} | |
my $stop = $start + $seconds_per_day; | |
my($gather, $yield) = gather_mtime_between($start, $stop); | |
find($gather, @starting_directories); | |
my @files = $yield->( ); | |
for my $file (@files) { | |
my $mtime = (stat $file)[9]; # mtime via slice | |
my $when = localtime $mtime; | |
print "$when: $file\n"; | |
} | |
sub gather_mtime_between { | |
my $start_time = shift; | |
my $end_time = shift; | |
my @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, canonpath( $File::Find::name ) | |
if ($when >= $start_time and $when <= $end_time) }, | |
sub { @files = no_upwards( @files ); | |
wantarray ? @files : [ @files ] } | |
} | |
# Here is the 'official' answer for Chapter 7 | |
sub gather_mtime_between { | |
my($begin, $end) = @_; | |
my @files; | |
my $gatherer = sub { | |
my $timestamp = (stat $_)[9]; | |
unless (defined $timestamp) { | |
warn "Can't stat $File::Find::name: $!, skipping\n"; | |
return; | |
} | |
push @files, $File::Find::name | |
if $timestamp >= $begin and $timestamp <= $end; | |
}; | |
my $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. | |
# If we omit that check, we can get warnings of an undefined value | |
# during the comparison with begin time and end time. | |
############################################################################ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment