########################################################################## 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-27 23:19:22 发布
本文详细解读了《中级Perl》一书中章节7的练习题,包括使用File::Find模块进行文件查找、本地时间处理及目录遍历等关键概念。通过实际代码演示,帮助读者理解如何在Perl中高效地进行文件操作。
637

被折叠的 条评论
为什么被折叠?



