您的位置:首页 > 其它

Exercise for Chapter 7 of "Intermediate Perl"

2012-12-23 12:31 344 查看
#########################################################################
#  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. 
# 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.
############################################################################
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐