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

Good Morning Monks, I have written a FTP script but I need to have the script only get the latest file. I know, it is not as easy as selecting a maximum date. Should I list the directory into an array to select the last entry. Do you have any suggestions on how to do it? Thanks.

Replies are listed 'Best First'.
Re: Get the latest file
by sgifford (Prior) on May 18, 2004 at 15:46 UTC
    Are you using Net::FTP? You can get the modification times with that module, then look for the file with the newest modification time. For example:
    #!/usr/bin/perl use Net::FTP; my $ftp = Net::FTP->new('ftp.cpan.org', Debug => 1) or die "Couldn't connect\n"; $ftp->login('anonymous','') or die "Couldn't log in\n"; my $newestfile; my $newesttime = 0; foreach my $file ($ftp->ls) { my $mdtm = $ftp->mdtm($file) or next; if ($mdtm > $newesttime) { $newestfile = $file; $newesttime = $mdtm; } } print "Getting file '$file'\n"; $ftp->get($newestfile);
Re: Get the latest file
by Abigail-II (Bishop) on May 18, 2004 at 15:40 UTC
    This may be impossible - it will depend on your FTP server. You have to issue a dir() command, this will give a "long listing" of the remote directory. Often this will include a timestamp (which you will have to parse yourself), but I've encountered FTP servers that only list the file names, and nothing else. IIRC, there isn't a fixed format, although output similar to "ls -l" is common.

    The last entry returned will often not be the latest file.

    Abigail

      You don't have to parse it yourself, you can use File::Listing instead.
Re: Get the latest file
by biosysadmin (Deacon) on May 18, 2004 at 15:53 UTC
    As Abigal-II has pointed out, not all FTP servers support transmitting file modification times, and the ones that do may not even transmit them in the same format. I think you have two options:
    • Write a client-side script to parse the output of "ls -l" and grab the latest file
    • Write a server-side script that symlinks the latest file to a known filename, such as "latest"
    Here's some example code for the second way of doing things. Some example code is shown below:
    #!/usr/bin/perl -w use strict; my $ftp_dir = '/pub/'; my @files = glob("$ftp_dir/*"); my ($latest_file,$modtime) = (0,0); foreach my $file (@files) { my $local_modtime = (stat($file))[9]; if ( $local_modtime > $modtime ) { $latest_file = $file; $modtime = $local_modtime; } } # There's probably a better way to make symlinks `ln -s $ftp_dir/$latest_file $ftp_dir/latest`;
    The code is untested, but hopefully it can get the point across.
Re: Get the latest file
by saintmike (Vicar) on May 18, 2004 at 16:12 UTC
    Check out this node on how to parse the timestamps coming back from Net::FTP's dir() method.

    With this tool under your belt, you'll probably come up with something like this:

    use warnings; use strict; use Net::FTP; use File::Listing; use List::Util qw(reduce); my $ftp = Net::FTP->new('ftp.host.com'); $ftp->login('username', 'password'); my $latest = reduce { $b->[3] < $a->[3] ? $a : $b } File::Listing::parse_dir($ftp->dir()); print "Last modified file is: '$latest->[0]'\n";