Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 337
Tom Feiner Avatar asked Nov 30 '08 09:11

Tom Feiner


People also ask

How do I find the latest generated file in Linux?

The command: ls -1c | head -1 will find the latest inode creation time.

How do I find the last modified file?

File Explorer has a convenient way to search recently modified files built right into the “Search” tab on the Ribbon. Switch to the “Search” tab, click the “Date Modified” button, and then select a range. If you don't see the “Search” tab, click once in the search box and it should appear.

How will check the last update of a directory or a file?

Use the cd command to access the directory containing the files you want to see the modification date. Then, use the ls command to list all files in the current directory. We recommend using the ls command below to give you the best listing of files, including the modification date.


2 Answers

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

like image 185
7 revs Avatar answered Oct 03 '22 16:10

7 revs


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"; } 
like image 30
brian d foy Avatar answered Oct 03 '22 14:10

brian d foy