22

Perl でディレクトリ内の最新のファイルを見つけるための洗練された方法はありますか (変更日で最新)?

私がこれまでに持っているのは、必要なファイルを検索することであり、それぞれが変更時間を取得し、ファイル名と変更時間を含む配列にプッシュしてから並べ替えます。

もっと良い方法があるはずです。

4

6 に答える 6

26

ソートされたリストが必要な場合、あなたの方法は「正しい」方法です(最初のものだけでなく、ブライアンの答えを参照してください)。そのコードを自分で書きたくない場合は、これを使用してください

use File::DirList;
my @list = File::DirList::list('.', 'M');

個人的には、ls -t別のプログラムをフォークする必要があり、移植性がないという方法には行きません。私が「エレガント」と呼ぶものはほとんどありません!


rjray のソリューション ハンド コード ソリューションに関しては、少し変更します。

opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
my @files = map { [ stat "$DIR/$_", $_ ] } grep(! /^\.\.?$/, readdir($DH));
closedir($DH);

sub rev_by_date { $b->[9] <=> $a->[9] }
my @sorted_files = sort rev_by_date @files;

この後@sorted_filesに、ソートされたリストが含まれます。ここで、0 番目の要素は最新のファイルであり、各要素自体には の結果への参照が含まstatれ、最後の要素にファイル名自体があります。

my @newest = @{$sorted_files[0]};
my $name = pop(@newest);

これの利点は、必要に応じて後で並べ替え方法を簡単に変更できることです。


編集: これはディレクトリ スキャンの読みやすい (ただし長い) バージョンで、プレーン ファイルのみがリストに追加されるようにします。

my @files;
opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
while (defined (my $file = readdir($DH))) {
  my $path = $DIR . '/' . $file;
  next unless (-f $path);           # ignore non-files - automatically does . and ..
  push(@files, [ stat(_), $path ]); # re-uses the stat results from '-f'
}
closedir($DH);

注意: のdefined()結果に対するテストはreaddir()、'0' というファイルが原因でループが失敗するためです。if (my $file = readdir($DH))

于 2008-11-30T14:41:00.290 に答える
15

すべての変更時刻とファイル名をリストに保持する必要はありません。おそらくそうすべきではありません。必要なことは、1 つのファイルを見て、以前に見た中で最も古いファイルよりも古いかどうかを確認することだけです。

{
    opendir my $dh, $dir or die "Could not open $dir: $!";

    my( $newest_name, $newest_time ) = ( undef, 2**31 -1 );

    while( defined( my $file = readdir( $dh ) ) ) {
        my $path = File::Spec->catfile( $dir, $file );
        next if -d $path; # skip directories, or anything else you like
        ( $newest_name, $newest_time ) = ( $file, -M _ ) if( -M $path < $newest_time );
    }

    print "Newest file is $newest_name\n";
}
于 2008-11-30T17:25:59.850 に答える
11

lsシェルのコマンドを使用して試すことができます:

@list = `ls -t`;
$newest = $list[0];
于 2008-11-30T09:51:37.287 に答える
6

$DIR調べたいことがわかっていると仮定します。

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);
# $sorted_files[0] is the most-recently modified. If it isn't the actual
# file-of-interest, you can iterate through @sorted_files until you find
# the interesting file(s).

フィルターを「。」grepで囲みます。readdirUNIX(-ish)ファイルシステムの「..」特殊ファイル。

于 2008-11-30T09:52:25.443 に答える
2

@Nathanが提案するように並べ替えを実行できない場合はls、これまでに表示された最新の変更時間と関連するファイル名のみを保持し、ディレクトリで新しいファイルが見つかるたびにそれを置き換えることで、プロセスを最適化できます。これまでに見た最新のファイルよりも古いことがわかっているファイルを保持する必要はありません。また、ディレクトリからの読み取り中に最新のファイルを検出できるため、ファイルを並べ替える必要もありません。

于 2008-11-30T13:52:01.137 に答える
-1

件名は古いですが、誰かが試してみるかもしれません-移植性はありません(Unixライクなシステムのみ)が、非常にシンプルで機能します:

chdir$directoryまたはdie「ディレクトリを変更できません」;

私の$newest_file= bash -c 'ls -t | head -1';

$newest_fileを切り刻む;

印刷"$newest_file \ n";

于 2012-04-10T23:18:19.697 に答える