How can I find the newest created file in a directory?

旧巷老猫 提交于 2019-12-29 05:04:45

问题


Is there an elegant way in Perl to find the newest file in a directory (newest by modification date)?

What I have so far is searching for the files I need, and for each one get it's modification time, push into an array containing the filename, modification time, then sort it.

There must be a better way.


回答1:


Your way is the "right" way if you need a sorted list (and not just the first, see Brian's answer for that). If you don't fancy writing that code yourself, use this

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

Personally I wouldn't go with the ls -t method - that involves forking another program and it's not portable. Hardly what I'd call "elegant"!


Regarding rjray's solution hand coded solution, I'd change it slightly:

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;

After this, @sorted_files contains the sorted list, where the 0th element is the newest file, and each element itself contains a reference to the results of stat, with the filename itself in the last element:

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

The advantage of this is that it's easier to change the sorting method later, if desired.


EDIT: here's an easier-to-read (but longer) version of the directory scan, which also ensures that only plain files are added to the listing:

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);

NB: the test for defined() on the result of readdir() is because a file called '0' would cause the loop to fail if you only test for if (my $file = readdir($DH))




回答2:


You don't need to keep all of the modification times and filenames in a list, and you probably shouldn't. All you need to do is look at one file and see if it's older than the oldest you've previously seen:

{
    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";
}



回答3:


you could try using the shell's ls command:

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



回答4:


Assuming you know the $DIR you want to look in:

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).

The grep that wraps the readdir filters out the "." and ".." special files in a UNIX(-ish) filesystem.




回答5:


If you can't let ls do the sorting for you as @Nathan suggests, then you can optimize your process by only keeping the newest modification time and associated filename seen thus far and replace it every time you find a newer file in the directory. No need to keep any files around that you know are older than the newest one you've seen so far and certainly no need to sort them since you can detect which is the newest one while reading from the directory.




回答6:


Subject is old, but maybe someone will try it - it isn't portable (Unix-like systems only), but it's quite simple and works:

chdir $directory or die "cannot change directory";

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

chomp $newest_file;

print "$newest_file \n";



来源:https://stackoverflow.com/questions/328673/how-can-i-find-the-newest-created-file-in-a-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!