Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

sorting files by date

by Win (Novice)
on Feb 05, 2007 at 10:40 UTC ( #598264=perlquestion: print w/replies, xml ) Need Help??
Win has asked for the wisdom of the Perl Monks concerning the following question:

I have a bit of code as follows:
opendir (LOWEST, "<$input_directory_lowest") or die "Error opening d +irectory: $!"; foreach (sort grep(/^Flat_file.*\.txt$/,readdir(LOWEST))) { push @lowest_priority,$_; } closedir LOWEST;
What is the most efficient way of sorting the files in @lowest_priority by time created. I would like to do this in the foreach clause, if this is the best way of doing it.

Replies are listed 'Best First'.
Re: sorting files by date
by davorg (Chancellor) on Feb 05, 2007 at 10:57 UTC

    Look at the three file test operators -M, -A and -C and decide which of them best mirrors your "time created". Let's assume it's -M.

    The naive way to sort a list of files then becomes:

    my @sorted_files = sort { -M $a <=> -M $b } @files;

    But you specifically asked for an efficient method, so you'll probably want to replace that with an Orcish Maneuver or a Schwartzian Transform. See Uri Guttman and Larry Rosler's excellent paper for discussion of these methods and other Perl sorting mechanisms.

    Also, you have this code:

    opendir (LOWEST, "<$input_directory_lowest")

    I think you're confusing open and opendir. for opendir you don't need the '<' on the directory name. In fact, I'm surprised to see that it works.

      Out of interest, is it possible to do something like:
      my @sorted_files = sort { -M -w $a <=> -M -w $b } @files;
      Update: What I really mean to ask is: can serveral clauses be put in here?

        Well given that you haven't bothered to explain what you want it to do, it's impossible to answer that question.

        Update: Win added this "clarification":

        Update: What I really mean to ask is: can serveral clauses be put in here?

        What does the documentation say? Or what happened when you tried it out?

        I don't think you're really thinking this through (tho' I don't know why I'd expect you too given your past form).

        Think about what you're asking. -M file returns a number that represents the modification date of the file. -w file returns a flag (true or false) that indicates whether the file is writable. What could -M -w file possibly return that would be at all meaningful? I can understand how you might want to write something like -r -w file to test if a file is both readable and writable[1] but I can't see any possible use for -M -w file.

        Please give some thought to what you're asking before bothering us with it. Try to, at least, understand how it might all work.

        [1] It doesn't work in Perl 5, but I think it's planned for Perl 6.

      Would a foreach statement return the oldest file first when reading through the sorted array (by method given by davorg)?
        Would a foreach statement return the ...

        What does the documentation say about the return value of foreach?

Re: sorting files by date
by marto (Bishop) on Feb 05, 2007 at 11:04 UTC

    Did you learn nothing from your previous posts Sort files and No. files in folder? The advice that davorg has given you, it would seem you already knew (at lease some of this) based on your code you posted in No. files in folder, to which other monks replied giving you help.

      Good point marto. Sorry, I've been away from Perl for some time. Quite right my hands should be slapped. I was kind of wondering if the files would be best sorted at the grep stage. But I suppose that these files would all have to be read in anyway, and so it would not be more efficient to do it at the grep stage.
        No hand slapping required (it's not that kind of forum :P). I find that if I have not used a function/module for a long time, and I feel that I would require/benefit from getting to grips with it again, I find a quick re read of the documentation refreshes my mind. In some cases I will look at my notes to see if I have done something similar in the past. In this case the Monastery provides Perl Monks User Search and Super Search which are very helpful.


        Update: Updated link to Perl Monks User Search
        I was kind of wondering if the files would be best sorted at the grep stage. But I suppose that these files would all have to be read in anyway, and so it would not be more efficient to do it at the grep stage.

        Good question! I believe the answer is that it's best to sort last, after the grep, since it's a more expensive operation, and therefore better to work it on a shorter list of values.

        sort { -M $a <=> -M $b } grep { -w $_ } @files
        A word spoken in Mind will reach its own level, in the objective world, by its own weight
Re: sorting files by date
by shmem (Chancellor) on Feb 05, 2007 at 13:47 UTC
    opendir (LOWEST, "<$input_directory_lowest")

    Please re-read chromatics answer to one of your previous posts, and follow the advice therein. Read opendir and readdir.

    The syntax for opendir is not the same as for open. You must not specify an open mode via < or >, since directories are never opened for writing.


    _($_=" "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}
Re: sorting files by date
by Moron (Curate) on Feb 05, 2007 at 14:01 UTC
    For efficiency purposes, the trap to avoid is allowing sort to do a -M on the same file each time it lands on that file during the sorting algorithm - the ||= operator can be useful in this regard...
    my %filedate; my @lowest_priority = sort { ( $filedate{ $a } ||= -M $a ) <=> ( $filedate{ $b } ||= -M $b ) } grep /^Flat_file.*\.txt$/, readdir LOWEST;


    Free your mind

Re: sorting files by date
by Thelonius (Priest) on Feb 06, 2007 at 16:18 UTC
    One thing that everybody here is forgetting is that unless you are doing a readdir on the current directory, you must prepend the directory name for -M, -C, stat, etc.

    Here are some ways to do it:

    #!perl -w use strict; use File::stat; # Method 1: my $input_directory_lowest = "pridir"; opendir (LOWEST, $input_directory_lowest) or die "Error opening directory: $!"; my @files; while (my $fname = readdir LOWEST) { if ($fname =~ /^Flat_file.*\.txt$/) { push @files, [stat("$input_directory_lowest/$fname")->ctime, $fname]; } } closedir(LOWEST); my @low1 = map { $_->[1] } sort {$a->[0] <=> $b->[0]} @files; print join("\n ", "low1=", @low1), "\n"; # Method 2: same as 1, but without explicit loop opendir (LOWEST, $input_directory_lowest) or die "Error opening directory: $!"; my @low2 = map { $_->[1] } sort {$a->[0] <=> $b->[0]} map { [ stat("$input_directory_lowest/$_")->ctime, $_ ] } grep /^Flat_file.*txt$/, readdir(LOWEST); closedir(LOWEST); print join("\n ", "low2=", @low2), "\n"; # Method 3: outputs file names with directory; uses 'glob' my @low3 = map { $_->[1] } sort {$a->[0] <=> $b->[0]} map { [ stat($_)->ctime, $_ ] } glob("$input_directory_lowest/Flat_file*.txt"); print join("\n ", "low3=", @low3), "\n";

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://598264]
Approved by Corion
[marinersk]: That has always been its behavior, but I'm a visual/spacial- awareness guy. When the node disappears, it messes with my head, even though it is on the right margin.
[marinersk]: I was hoping there was a way to turn it on and make it stay on.
[LanX]: what is the intention of your question?
[LanX]: why do you need to see the nodelet without votes left???

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2017-05-29 13:47 GMT
Find Nodes?
    Voting Booth?