How can I find the newest .pl file in a directory and in all its subdirectories using Perl?

How to scan the contents of an entire directory, including its contents in subdirectories, and find the newest .pl file in it using Perl?

I want to create a sorted array / list of full file paths of all .pl files in a directory tree.

So, for example, if my base directory is /home/users/cheeseconqueso/ , I want to search for .pl files in this directory and any subdirectory in this path, and then sort the .pl files by date.

The end result will be an array, @pl_paths , where $pl_paths[0] will be something like /home/users/cheeseconqueso/maybe_not_newest_directory/surely_newest_file.pl

From this result, I want to execute the file, but I think as soon as I get the sorted array by executing the file in $pl_paths[0] , there will be no problem.

There is the same question that I tried to change according to my needs, but I'm here for obvious reasons.

The code I use to get the newest NAME file in only one directory:

 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
source share
3 answers

You can use File :: Find if you need the main module, but I would prefer to use File :: Find :: Rule .

To get started, we can find all the .pl files in the directory with

 use File::Find::Rule; my @files = File::Find::Rule->file ->name('*.pl') ->in($directory); 

Then use map to associate file names with their modification time:

 my @files_with_mtimes = map +{ name => $_, mtime => (stat $_)[9] }, @files; 

And sort them by mtime:

 my @sorted_files = reverse sort { $a->{mtime} <=> $b->{mtime} } @files_with_mtimes; 

And from there, the name of the newest is in $sorted_files[0]{name} .

If you only want to find the top one, there really is no need to do a full-fledged sorting, but the most pleasant solution that I can think of is related to a slightly advanced FP, so don't worry about it at all if it looks strange to you:

 use List::Util 'reduce'; my ($top_file) = reduce { $a->{mtime} >= $b->{mtime} ? $a : $b } @files_with_mtimes; 
+12
source

With File :: Find :: Rule and Schwartz Transformation , you can get a new file with the extension .pl, in a subtree, starting with dir_path.

 #!/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 ]; 

A sorting map chain is a typical idiom: getting a timestamp is slow, so we only do this once for each file, saving each timestamp with its file in an arrayref file. Then we sort the new list using timestamp (compare the second element of each arrayref) and finally discard the timestamps, preserving only the file names.

+4
source

Use File :: Find Main Module.

+2
source

All Articles