当前位置:  开发笔记 > 编程语言 > 正文

Perl挑战 - 目录迭代器

如何解决《Perl挑战-目录迭代器》经验,为你挑选了5个好方法。

你有时会听到它说Perl可能有6种不同的方法来解决同样的问题.优秀的Perl开发人员通常有充分的理由在各种可能的实现方法之间做出选择.

所以Perl的一个例子问题:

一个简单的脚本,递归地遍历目录结构,查找最近修改过的文件(在某个特定日期之后,这将是可变的).将结果保存到文件.

问题,对于Perl开发人员:您最好的方法是什么?



1> pjf..:

这听起来像File :: Find :: Rule的工作:

#!/usr/bin/perl
use strict;
use warnings;
use autodie;  # Causes built-ins like open to succeed or die.
              # You can 'use Fatal qw(open)' if autodie is not installed.

use File::Find::Rule;
use Getopt::Std;

use constant SECONDS_IN_DAY => 24 * 60 * 60;

our %option = (
    m => 1,        # -m switch: days ago modified, defaults to 1
    o => undef,    # -o switch: output file, defaults to STDOUT
);

getopts('m:o:', \%option);

# If we haven't been given directories to search, default to the
# current working directory.

if (not @ARGV) {
    @ARGV = ( '.' );
}

print STDERR "Finding files changed in the last $option{m} day(s)\n";


# Convert our time in days into a timestamp in seconds from the epoch.
my $last_modified_timestamp = time() - SECONDS_IN_DAY * $option{m};

# Now find all the regular files, which have been modified in the last
# $option{m} days, looking in all the locations specified in
# @ARGV (our remaining command line arguments).

my @files = File::Find::Rule->file()
                            ->mtime(">= $last_modified_timestamp")
                            ->in(@ARGV);

# $out_fh will store the filehandle where we send the file list.
# It defaults to STDOUT.

my $out_fh = \*STDOUT;

if ($option{o}) {
    open($out_fh, '>', $option{o});
}

# Print our results.

print {$out_fh} join("\n", @files), "\n";


没有"标准"模块这样的东西.如果你的意思是与perl捆绑在一起的模块,那么它们分为两类:历史的,或用于安装其他模块的; 这两者都不是一个很好的理由,更喜欢那些来自CPAN的东西.

2> Philip Reyno..:

问题主要由标准库解决,使用它们.

File :: Find在这种情况下效果很好.

在perl中可能有很多方法可以做,但是如果存在一个非常标准的库来执行某些操作,除非它有自己的问题,否则应该使用它.

#!/usr/bin/perl

use strict;
use File::Find();

File::Find::find( {wanted => \&wanted}, ".");

sub wanted {
  my (@stat);
  my ($time) = time();
  my ($days) = 5 * 60 * 60 * 24;

  @stat = stat($_);
  if (($time - $stat[9]) >= $days) {
    print "$_ \n";
  }
}



3> dland..:

没有六种方法可以做到这一点,有旧方式和新方法.旧的方法是使用File :: Find,你已经有了几个例子.File :: Find有一个非常糟糕的回调接口,它在20年前很酷,但从那时起我们就开始了.

这是一个真实的生活(轻微修改)程序,我用它来清除我的一个生产服务器上的残骸.它使用File :: Find :: Rule,而不是File :: Find.File :: Find :: Rule有一个很好的声明性接口,可以轻松读取.

Randal Schwartz还编写了File :: Finder,作为File :: Find的包装器.这很不错但它还没有真正起飞.

#! /usr/bin/perl -w

# delete temp files on agr1

use strict;
use File::Find::Rule;
use File::Path 'rmtree';

for my $file (

    File::Find::Rule->new
        ->mtime( '<' . days_ago(2) )
        ->name( qr/^CGItemp\d+$/ )
        ->file()
        ->in('/tmp'),

    File::Find::Rule->new
        ->mtime( '<' . days_ago(20) )
        ->name( qr/^listener-\d{4}-\d{2}-\d{2}-\d{4}.log$/ )
        ->file()
        ->maxdepth(1)
        ->in('/usr/oracle/ora81/network/log'),

    File::Find::Rule->new
        ->mtime( '<' . days_ago(10) )
        ->name( qr/^batch[_-]\d{8}-\d{4}\.run\.txt$/ )
        ->file()
        ->maxdepth(1)
        ->in('/var/log/req'),

    File::Find::Rule->new
        ->mtime( '<' . days_ago(20) )
        ->or(
            File::Find::Rule->name( qr/^remove-\d{8}-\d{6}\.txt$/ ),
            File::Find::Rule->name( qr/^insert-tp-\d{8}-\d{4}\.log$/ ),
        )
        ->file()
        ->maxdepth(1)
        ->in('/home/agdata/import/logs'),

    File::Find::Rule->new
        ->mtime( '<' . days_ago(90) )
        ->or(
            File::Find::Rule->name( qr/^\d{8}-\d{6}\.txt$/ ),
            File::Find::Rule->name( qr/^\d{8}-\d{4}\.report\.txt$/ ),
        )
        ->file()
        ->maxdepth(1)
        ->in('/home/agdata/redo/log'),

) {
    if (unlink $file) {
        print "ok $file\n";
    }
    else {
        print "fail $file: $!\n";
    }
}

{
    my $now;
    sub days_ago {
        # days as number of seconds
        $now ||= time;
        return $now - (86400 * shift);
    }
}



4> Leon Timmerm..:

File :: Find是解决此问题的正确方法.重新实现其他模块中已经存在的东西是没有用的,但是应该不鼓励重新实现标准模块中的某些东西.



5> runrig..:

其他人提到了File :: Find,这就是我要去的方式,但是你要求一个迭代器,File :: Find不是(也不是File :: Find :: Rule).您可能希望查看File :: Next或File :: Find :: Object,它们具有迭代接口.Mark Jason Dominus在高阶Perl的 4.2.2章中继续构建自己的.

推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有