########################################################################## 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 todaywhile ( $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 slicemy $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 7sub 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:: nameif $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.# 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.############################################################################
Exercise for Chapter 7 of "Intermediate Perl"
最新推荐文章于 2019-01-16 17:33:10 发布