#!/usr/bin/perl
#######################################################################

=head1 NAME

newest - find newest file



=head1 VERSION

$Id: newest,v 1.13 2009-05-01 15:47:21 dpchrist Exp $



=head1 SYNOPSIS

newest [options] PATH...

    @ARGVFILE           Insert command line arguments from ARGVFILE
    --debug, -d         Generate debug messages
    --help, -h, -?      Print a brief help message
    --man               Print the manual page
    --number, -n N      Print the N newest files



=head1 DESCRIPTION

B<newest> will recursively search all files and folders given by PATH
and print the absolute path of the newest file.  If more than one file
has the same newest time stamp, only print one file.



=head1 COPYRIGHT AND LICENSE

Copyright 2009 by David Paul Christensen  dpchrist@holgerdanske.com

This software is released under the terms of the Artistic License 2.0,
as published by The Perl Foundation.  Please see the file LICENSE.txt
in the source distribution or The Perl Foundation web site at
http://www.perlfoundation.org/.

=cut

#######################################################################
# uses:
#----------------------------------------------------------------------

use strict;
use warnings;

use Data::Dumper;
$Data::Dumper::Sortkeys = 1;

use Dpchrist::Timestamp		qw( :all );
use File::Spec::Functions	qw( catfile rel2abs );
use File::Find;
use Getopt::Long;
use Pod::Usage;
use Time::localtime;

#######################################################################
# globals:
#----------------------------------------------------------------------

$| = 1;

our $VERSION = sprintf "%d.%03d", q$Revision: 1.13 $ =~ /: (\d+)\.(\d+)/;

##### command line option values:
my $debug		= 0;
my $help		= 0;
my $man			= 0;
my $notime		= 0;
my $number		= 1;

##### parameters for GetOption():
my @GetOptions_parms = (
    'debug|d'           => \$debug,
    'help|h|?'          => \$help,
    'man'               => \$man,
    'number|n=i'	=> \$number,
);

##### data structure:
my %mtimes_paths;
#	key	is file modification time
#	value	is a reference to a list containing file paths

#######################################################################
# subroutines:
#----------------------------------------------------------------------

sub process
{
    my $path = rel2abs($File::Find::name);
    
    return if -d $path;
    
    my $mtime = (stat($path))[9] || 0;

    print join ' ', __FILE__, __LINE__, (caller(0))[3] . "()\n",
	Data::Dumper->Dump([$path, $mtime], [qw(path mtime)])
	if $debug;

    push(@{$mtimes_paths{$mtime}}, $path);
}

#######################################################################
# main script:
#----------------------------------------------------------------------

{
    GetOptions(@GetOptions_parms) or pod2usage(2);

    pod2usage(-verbose => 2) if $man;
    pod2usage() if $help || scalar(@ARGV) < 1;
    
    ##### fills global variable %mtime_paths
    find(\&process, @ARGV);

    print join ' ', __FILE__, __LINE__, (caller(0))[3] . "()\n",
	Data::Dumper->Dump([\%mtimes_paths], [qw(*mtimes_paths)])
	if $debug;

    my @mtimes = sort keys %mtimes_paths;
    print join ' ', __FILE__, __LINE__, (caller(0))[3] . "()\n",
	Data::Dumper->Dump([\@mtimes], [qw(*mtimes)])
	if $debug;

    while ($number--) {

	# mtime of newest file(s):
	my $t = pop @mtimes;	

	# first file with that mtime:
	my $f = shift @{$mtimes_paths{$t}};

	print join ' ', __FILE__, __LINE__, (caller(0))[3] . "()\n",
	    Data::Dumper->Dump([$t, $f], [qw(t f)])
	    if $debug;

	print "$f\n";
    }
}

#######################################################################
