Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

read directory

by Zcity (Novice)
on Jul 08, 2006 at 00:35 UTC ( #559887=perlquestion: print w/ replies, xml ) Need Help??
Zcity has asked for the wisdom of the Perl Monks concerning the following question:

How do you get the read directory function to sort by latest modified date???

Any advice? Thanks in advance.

use CGI ':standard'; use strict; use CGI::Carp qw/fatalsToBrowser/; use File::Spec::Functions; opendir( FILES, "pending" ) || die "Cannot opendir /some/path: $!"; print "Content-type: text/html\n\n"; print "<TABLE BORDER=1>\n<TR><TH align=left>Files</TH><TH align=left>Last Modified On</TH> </TR>"; my $files; my $mod; while ( $files = readdir(FILES) ) { $mod = ( stat( catfile( 'pending', $files ) ) )[9]; $mod = localtime($mod); # href will have path to new cgi print "<TR><TD><a href=createhtml.cgi?filename=" . $files . ">$files</a></TD><TD>$mod</TD> </TR>"; } print "</TABLE>"; closedir(FILES); sub Error { print "Content-type: text/html\n\n"; print "The server can't $_[0] the $_[1]: $! \n"; exit; }

Comment on read directory
Download Code
Re: read directory
by jbisbee (Pilgrim) on Jul 08, 2006 at 01:08 UTC
    Here is a quick example using glob, map, and sort to produce a list of files and their modified times. It's not quite a Swartzian transform, because we leave the modified time hanging around for the output.
    #!/usr/bin/perl use strict; use warnings; use CGI qw(:standard); my %cache = (); my @files = sort { $b->[1] <=> $a->[1] } map { [ $_, (stat($_))[9] ] } glob('pending/*'); print header; print "<table>\n"; for my $file (@files) { print "<tr><td>$file->[0]</td><td>" . localtime( $file->[1] ) . "</td></tr>\n"; } print "</table>\n";
    also in the future, put <code></code> around code you post :)


Re: read directory
by shmem (Canon) on Jul 08, 2006 at 10:49 UTC
    You don't. readdir (and glob) return the entries in the order the OS kernel pleases to present them. You have to sort yourself:
    @files = sort {-M $a <=> -M $b} <*>; # update - better without -M in sort opendir(D,$dir); @files = map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { [-M $_, $_] } grep {!/^\.\.?$/} readdir(D);

    A related thread is here.


    update: added ST after reading TedPride's post ;-)

    _($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                                  /\_/(q    /
    ----------------------------  \__(m.====.(_("always off the crowd"))."
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Update: Sorry, I know this post was a bit lame and didn't prove anything

      I just benchmarked the difference between "glob" and "<>" and found very little difference (subsequent runs flip-flopped which was faster). If that's the case, then I'd prefer the glob('pending/*') over the <pending/*> call because of the awkward bare word. But then, thats just me.

      #!/usr/bin/perl use strict; use warnings; use Benchmark qw(cmpthese); cmpthese( 20_000, { '<>' => sub { my @results = <pending/*>; }, 'glob' => sub { my @results = glob('pending/*'); }, }, );
      and the results
      Rate glob <> glob 7194/s -- -0% <> 7220/s 0% --


        well, <DATA> also has a bareword.. ;-)

        I'm not surprised that glob and <> down differ much, since they are essentially the same... bigger savings can be achieved by using -M instead of (stat)[9], because doing so eliminates the overhead of making a list just to get its 10th element.


        _($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                                      /\_/(q    /
        ----------------------------  \__(m.====.(_("always off the crowd"))."
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        I just benchmarked the difference between "glob" and "<>" and found very little difference

        That's hardly surprising since glob is the internal function implementing the "<*.c>" operator according to the documentation.

        David Serrano

Re: read directory
by TedPride (Priest) on Jul 08, 2006 at 20:07 UTC
    It might be more efficient to call ls, if the number of files in the directory is large. You certainly don't want to call -M from inside a sort, as shmem suggests.

    my @files = split /\n/, `ls -1t`; for (@files) { ... }
    The -1 modifier forces output to one column, and -t sorts by last time modified.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://559887]
Approved by prasadbabu
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (16)
As of 2014-07-30 08:24 GMT
Find Nodes?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:

    Results (229 votes), past polls