【问题标题】:How can I find the newest .pl file in a directory and all its subdirectories using Perl?如何使用 Perl 在目录及其所有子目录中找到最新的 .pl 文件?
【发布时间】:2011-09-28 14:51:13
【问题描述】:

如何使用 Perl 扫描整个目录的内容,包括其子目录的内容,并在其中找到最新的 .pl 文件?

我想为目录树中所有.pl 文件的完整文件路径构建一个排序数组/列表。

因此,例如,如果我的基本目录是 /home/users/cheeseconqueso/,我想在该目录和该路径中的任何子目录中搜索 .pl 文件,然后按日期对 .pl 文件进行排序。

最终结果将是一个数组@pl_paths,其中$pl_paths[0] 将类似于/home/users/cheeseconqueso/maybe_not_newest_directory/surely_newest_file.pl

根据该结果,我想执行该文件,但我认为一旦找出排序后的数组,在$pl_paths[0] 中执行该文件就不会成为问题。

有一个关于 SO 的similar 问题,我一直在尝试修改它以满足我的需要,但我现在在这里是出于显而易见的原因。

我用来在一个目录中获取最新文件 NAME 的代码是:

opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
my %files = map { $_ => (stat("$DIR/$_"))[9] } grep(! /^\.\.?$/, readdir($DH));
closedir($DH);
my @sorted_files = sort { $files{$b} <=> $files{$a} } (keys %files);
print $sorted_files[0]."\n";

【问题讨论】:

    标签: perl path directory file-search datecreated


    【解决方案1】:

    如果你想要一个核心模块,你可以使用File::Find,但我更喜欢使用File::Find::Rule

    首先,我们可以在一个目录下找到所有.pl文件

    use File::Find::Rule;
    my @files = File::Find::Rule->file
                                ->name('*.pl')
                                ->in($directory);
    

    然后让我们使用map 将文件名与其修改时间相关联:

    my @files_with_mtimes = map +{ name => $_, mtime => (stat $_)[9] }, @files;
    

    并按 mtime 排序:

    my @sorted_files = reverse sort { $a->{mtime} <=> $b->{mtime} } 
                    @files_with_mtimes;
    

    从那里,最新的名称在$sorted_files[0]{name}

    如果你只想找到最上面的,其实没必要做一个完整的排序,但是我能想到的最好的解决方案涉及一些稍微高级的FP,所以如果它看起来很奇怪完全不用担心给你:

    use List::Util 'reduce';
    my ($top_file) = reduce { $a->{mtime} >= $b->{mtime} ? $a : $b } 
      @files_with_mtimes;
    

    【讨论】:

    • 我认为您误读了问题中的某些内容......我正在寻找最新的文件,而不是最大的文件
    • @CheeseConQueso 哎呀!稍后会更新。不过同样的想法也适用!
    • @Zaid 它不能,加号是为了确保它被解释为代码块;这是一个 hashref。
    • map 旁边欺骗性地使用 hashref,我想在可选的代码块卷曲中穿上它是个人喜好问题。
    • reverse sort { f($a) &lt;=&gt; f($b) } @list也可以写成sort { f($b) &lt;=&gt; f($a) } @list
    【解决方案2】:

    使用File::Find::RuleSchwartzian transform,您可以在从 dir_path 开始的子树中获取带有 .pl 扩展名的最新文件。

    #!/usr/bin/env perl
    
    use v5.12;
    use strict;
    use File::Find::Rule;
    
    my @files = File::Find::Rule->file()->name( '*.pl' )->in( 'dir_path' );
    
    # Note that (stat $_ )[ 9 ] yields last modified timestamp
    @files = 
       map { $_->[ 0 ] }
       sort { $b->[ 1 ] <=> $a->[ 1 ] }
       map { [ $_, ( stat $_ )[ 9 ] ] } @files;
    
    # Here is the newest file in path dir_path
    say $files[ 0 ];
    

    map-sort-map 链是一个典型的习惯用法:获取时间戳很慢,所以我们每个文件只做一次,将每个时间戳与其文件保存在一个数组引用中。然后我们使用时间戳对新列表进行排序(比较每个 arrayref 的第二个元素),最后我们丢弃时间戳,只保留文件名。

    【讨论】:

      【解决方案3】:

      使用File::Find 核心模块。

      【讨论】:

        猜你喜欢
        • 2012-09-13
        • 1970-01-01
        • 2014-03-08
        • 2017-03-15
        • 1970-01-01
        • 1970-01-01
        • 2012-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多