ovedpo15 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I want to build a subroutine which returns the latest modified file in an array of files (could be regular file, link or directory).
The area is given in $base_dir variable and the filenames list hash ref is given in $filenames_href (The keys are the number and the values are just "1").
The initial code:
sub test { my ($base_dir,$filenames_href) = @_; foreach my $filename (keys(%{$filenames_href})) { my $file_path = catfile($base_dir,$filename); # Could be file, + dir, link, ... # TODO: Check if the $file_path is the latest I seen ? } return $latest_modified_file; }
For example:
ls -la . -rw-r----- 1 user group 33659 Nov 3 14:49 a drwxr-x--- 3 user group 4096 May 3 2021 b drwxr-x--- 3 user group 4096 Dec 8 16:18 c -rwxr-x--x 1 user group 67 Apr 5 2021 e drwxr-x--- 4 user group 4096 Nov 1 15:29 f -rw-r----- 1 user group 798 Nov 15 17:00 g
In that case the sub should return c because it was modified latest. Is there a standard way to do it?

Replies are listed 'Best First'.
Re: Getting latest modified file in a directory
by hippo (Archbishop) on Jan 10, 2022 at 16:24 UTC
    Is there a standard way to do it?

    No but there are many ways to do it. Here is one:

    #!/usr/bin/env perl use strict; use warnings; use List::Util 'reduce'; use Path::Tiny 'path'; my @files = qw/a b c/; my $dir = '/tmp/'; print newest($dir, @files) . "\n"; sub newest { my $dir = shift; my $newest = reduce { $a->stat->mtime > $b->stat->mtime ? $a : $b +} map { path "$dir/$_" } @_; return "$newest"; }

    I've passed the files as an array since that is much more useful (in a generic sense) than your hashref. Feel free to modify for your own purposes, of course. If your list of files is (or might be) very long then consider a transform to avoid excessive stat calls.


    🦛

Re: Getting latest modified file in a directory
by tybalt89 (Monsignor) on Jan 10, 2022 at 21:08 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11140328 use warnings; use List::AllUtils qw( max_by ); my $latest = max_by { (stat)[9] } glob 'tmp*'; # or your file list print "latest = $latest\n";
Re: Getting latest modified file in a directory
by Fletch (Bishop) on Jan 10, 2022 at 18:29 UTC

    Variation on the above theme for an instance if you actually wanted all of the files ordered newest to oldest and not just the newest:

    my @files_by_age = map { $_->[1] } sort { $b->[0]<=>$a->[0] } map { [ $_->stat->mtime, $_ ] } grep { $_->is_file } path( q{/tmp} )->children();

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Getting latest modified file in a directory -- oneliner
by Discipulus (Canon) on Jan 11, 2022 at 09:34 UTC
    perl -E "say+(sort{(stat$a)[9]<=>(stat$b)[9]}grep{-f}glob'*')[-1]"

    L*

    PS sorry.. the latest is indexed -1 not 0 which is the oldest

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.