web-dev-qa-db-ja.com

ディレクトリ内で新しく作成されたファイルを見つけるにはどうすればよいですか?

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

これまでのところ、必要なファイルを検索し、それぞれのファイルの変更時刻を取得し、ファイル名と変更時刻を含む配列にプッシュして、並べ替えます。

より良い方法があるに違いありません。

21
Tom Feiner

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

_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()のテストは、if (my $file = readdir($DH))のみをテストすると、「0」というファイルによってループが失敗するためです。

25
Alnitak

すべての変更時刻とファイル名をリストに保持する必要はありません。おそらくそうすべきではありません。あなたがする必要があるのは、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";
}
15
brian d foy

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

@list = `ls -t`;
$newest = $list[0];
11
Nathan Fellman

調べたい$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をラップするreaddirは、「。」を除外します。 UNIX(-ish)ファイルシステム内の「..」特殊ファイル。

6
rjray

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

2
tvanfosson