perlfg
perlfg

Reputation: 59

read the last modified file in perl

How can I read the content of the last modified file in a directory in perl

I have a tool for received sms and I want to give out the content of the last modified file , which is stored in gammu/inbox directory , with a perl script

for example: the script checked if a new sms in folder(gammu/inbox), are they, then give out the content from the last sms.

Upvotes: 0

Views: 534

Answers (2)

Borodin
Borodin

Reputation: 126722

Sort the directory according to the age of each file, using the -M file test operator. The most recently modified file will then be the first in the list

This program shows the principle. It finds the latest file in the current working directory, prints its name and opens it for input

If you want to do this for a directory other that the cwd then it is probably easiest just to chdir to it and use this code than to try to opendir a specific directory, as then you will have to build the full path to each file before you can use -M

use strict;
use warnings 'all';
use feature 'say';

my $newest_file = do {
    opendir my $dh, '.' or die $!;
    my @by_age  = sort { -M $a <=> -M $b } grep -f, readdir $dh;
    $by_age[0];
};

say $newest_file;

open my $fh, '<', $newest_file or die qq{Unable to open "$newest_file" for input: $!};

If you are working with a sizeable directory then this may take some time as a stat operation is quite slow. You can improve this a lot by using a Schwartzian Transform so that stat is called only once for each file

my $newest_file = do {

    opendir my $dh, '.' or die $!;

    my @by_age  = map $_->[0],
    sort { $a->[1] <=> $b->[1] }
    map [ $_, -M ], readdir $dh;

    $by_age[0];
};

If you want something really fast, then just do a single pass of the files, keeping track of the newest found so far. Like this

my $newest_file = do {

    opendir my $dh, '.' or die $!;

    my ($best_file, $best_age);

    while ( readdir $dh ) {

        next unless -f;
        my $age = -M _;

        unless ( defined $best_age and $best_age < $age ) {
            $best_age = $age;
            $best_file = $_;
        }
    }

    $best_file;
};

Upvotes: 3

Asasapd
Asasapd

Reputation: 7

You need to get an ordered list of file with

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

Than the first element of list is what you are looking for.

You can read more about the library here File::DirList

Upvotes: 0

Related Questions