4

.plサブディレクトリのコンテンツを含むディレクトリ全体のコンテンツをスキャンし、 Perlを使用してディレクトリ内の最新のファイルを見つけるにはどうすればよいですか?

.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についても同様の質問があり、自分のニーズに合わせて変更しようとしていますが、明らかな理由で今ここにいます。

1つのディレクトリでのみ最新のファイル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";
4

3 に答える 3

13

このためのコアモジュールが必要な場合は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;
于 2011-09-28T15:04:46.553 に答える
5

File :: Find :: Rule、およびSchwartzian変換を使用すると、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チェーンは典型的なイディオムです。タイムスタンプの取得は遅いため、ファイルごとに1回だけ実行し、すべてのタイムスタンプをそのファイルとともにarrayrefに保持します。次に、タイムスタンプを使用して新しいリストを並べ替え(各arrayrefの2番目の要素を比較)、最後にタイムスタンプを破棄して、ファイル名のみを保持します。

于 2011-09-28T15:30:58.020 に答える
2

File::Findコアモジュールを使用します。

于 2011-09-28T15:05:19.947 に答える