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

The following code gives me a table made from data in lots of small files. It works quite well. However I now need to make it list in date/time order with newest at the top.
opendir THEDIR, "$basepath$ARGV[0]" || die "Unable to open directory: +$!"; @allfiles = grep /^2/,readdir THEDIR; closedir THEDIR; $numfiles = @allfiles; $numfiles = ($numfiles - 2); foreach $file (sort { ($b) <=> ($a) } @allfiles) { if (-T "$basepath$ARGV[0]/$file") { $passflag = 0; open THEFILE, "$basepath$ARGV[0]/$file"; ($ref, $cust, $email, $phone, $mobile, $posted) = <DATAFILE>; close DATAFILE; chomp($ref, $cust, $email, $phone, $mobile, $posted); $file =~ s/\.DAT//; print"<TR><TD>$ref</td><TD>$cust</TD><TD>$email</TD><TD>$phone</TD><TD +>$posted</TD></TR>\n " unless ($passflag); print "</TABLE>\n"; }}}
Actually, I can do this by creating the filenames in a way that lets me sort them in date/time order (don't laugh I am a newbie to perl "year+dayofyear+hour+minute+a few random letters to avoid duplication" this gives me "1022001836abc.dat") this is no longer possible as the data i have to play with now, although holding the same information has a different naming system that I can't change "123456.dat" my question is, How can I create the same table listed in date/time order with the newest at the top regardless of what the filenames are?

Replies are listed 'Best First'.
Re: open, chomp, create AND sort ?
by BrowserUk (Patriarch) on Aug 10, 2002 at 11:47 UTC

    This is tested as far as it goes...you'll need to add validation of values and format the output:

    #! perl -w use strict; my $basedir = 'c:/test/'; opendir( THEDIR, $basedir) or die "Couldn't open '$basedir' $!"; my @list = map { $basedir . $_ } grep { -f "$basedir/$_" } readdir(THE +DIR); closedir (THEDIR) or warn "Close '$basedir' failed: $!"; my %files; for my $file (@list) { my $datetime = (stat $file)[9]; # or 8 or 10 - see perldoc + -f stat to choose. $files{$datetime} = $file; # save name for later } for my $datetime ( sort keys %files ) { my $file = $files{$datetime}; # retrieve name open DATAFILE, $file or warn "Failed to open $file: $!\n" and next +; $files{$datetime} = [<DATAFILE>]; # overwrite name with ref + to anon array of data. close DATAFILE or warn "Couldn't close $file: $!\n"; chomp @{$files{$datetime}}; # chomp all the values and +print them # You could assign these to discrete $vars to ease refs if you pre +fer # Or 'use constant REF => 0;' etc to make indexes more meaningful print @{$files{$datetime}}[0], # $ref @{$files{$datetime}}[1], # $cust @{$files{$datetime}}[2], # $email @{$files{$datetime}}[3], # $phone @{$files{$datetime}}[4], # $mobile @{$files{$datetime}}[5]; # $posted }
Re: open, chomp, create AND sort ?
by mephit (Scribe) on Aug 10, 2002 at 20:01 UTC
    It looks like just a matter of tweaking your sort subroutine. I haven't tested your code on my machine, but it looks like either a Schwartzian Transform or the Orcish Maneuver would work. You don't say what OS you're using, so I don't know that stat would work for you, but that's what I'll use here, as that's all I know of.

    Anyway, for an ST, you can presort your list of files with the following:

    my @sorted = map { $_->[0]} sort { $b->[1] <=> $a->[1] } map { [ $_, (stat $_)[9] ] } @allfiles;

    An Orcish Maneuver would be like the following:

    my %h; foreach $file (sort { ($h{$a} ||= (stat $a)[9]) <=> ($h{$b} ||= (stat $b)[9]) } @allfiles) { ...;
    There are probably other ways to do this, and I'm not quite sure how efficient either of these would be, but these are the only two that popped into my head. HTH.

    --

    There are 10 kinds of people -- those that understand binary, and those that don't.