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

Hello,

I am new to perl and am finding it difficult to populate and array with the latest files (files only) from a given directory.

I am using the system command ls -l to fetch the directory list.

Kindly advise.

thanks

Replies are listed 'Best First'.
Re: date sorted files into an array
by ccn (Vicar) on Aug 02, 2004 at 11:04 UTC

    this code prints files ordered by date

    my $some_dir = 'c:/'; opendir(DIR, $some_dir) || die "can't opendir $some_dir: $!"; @a = sort {(stat "$some_dir/$a")[9] <=> (stat "$some_dir/$b")[9]} grep { -f "$some_dir/$_" } readdir(DIR); closedir DIR; print join "\n", @a;

    see opendir, stat, readdir

Re: date sorted files into an array
by ysth (Canon) on Aug 02, 2004 at 11:09 UTC
    Perl offers two other ways to get files: glob and readdir.
    @files = glob "*.c"; # glob uses shell-like wildcards
    opendir DIRHANDLE, "." or die "couldn't open directory ."; @files = readdir DIRHANDLE; closedir DIRHANDLE;
    Either will get files or directories; glob by default will ignore names starting with a . To only get those files modified in the last 3 days (since the perl script started) and skip directories, you would then do:
    @files = grep -f && 3 > -M, @files;

      Great!! but that will limit the search to the past few days. It will not fetch the newest files outside the date range. It would be appropriate to get the latest available files irrespective of the current date or a specified date

        What the previous post mentions will get all the files, if you dont do the grep command. (the last command, separated from the others). You should probably do some reading. For this one, read about opendir().

        There is plenty of great documentation about built-in commands at perlmonks, but you should also get some books. I'd start with Programming Perl, published by O'Reilly & Assoc, if you have reasonable programming experience in other languages. - Its a great reference, particularly Chapter 29: Perl Funcitons in Alphabetical Order

        If you're new to programming in general, you may want to get O'reillys Learning Perl

Re: date sorted files into an array
by tbone1 (Monsignor) on Aug 02, 2004 at 13:07 UTC
    As long as you as using 'ls', why don't you use the '-t' option rather than '-l'? This sorts the files by date, rather than name. Combined with 'tail -n' or 'head -n', it can even get a fixed number for you, if that is what you need. Assuming you are on Unix, of course.

    Just a thought.

    --
    tbone1, YAPS (Yet Another Perl Schlub)
    And remember, if he succeeds, so what.
    - Chick McGee

Re: date sorted files into an array
by graff (Chancellor) on Aug 02, 2004 at 19:36 UTC
    Personally, I'd go with tbone1's idea: "ls -t" will list directory contents in reverse-cronological order (newest file first), while "ls -t -r" will do the opposite (oldest file first) -- assign the back-tick output to an array and you're done.

    If you want something that will work on systems that don't support "ls -t", then I think you should start with a hash, keyed by file name, with file ages as the values -- it involves doing a stat on each file just once (rather than multiple times within a sort block, as suggested in ccn's reply). Something like this:

    my %files; opendir( D, "." ); # or some specific path? -f and $files{$_} = -M _ for ( readdir D ); closedir D; my @newest_first = sort { $files{$a} <=> $files{$b} } keys %files;
    But if you're just running you code "in shop" (as opposed to including it in a package for open distribution), using "ls" with back-ticks is fine.
Re: date sorted files into an array
by superfrink (Curate) on Aug 03, 2004 at 03:49 UTC
    I'd probably use readdir and stat but here is kind of a fun way to use the system's find program. Plus it means you can use all the arguments that find supports like -ctime for example.
    #!/usr/bin/perl -w # purpose: use find program for getting a list of files into an array. # author: chad clark, 2004-08-02 use strict; use Data::Dumper; my $dir = "/tmp"; my $cmd = "find $dir -type f"; open LS, "$cmd|"; my @ls = <LS>; close LS; chomp @ls; print Dumper(\@ls); exit(0);