This quick little bit prints out the oldest file/directory in a the current directory. If you wish to print the newest entry just reverse the position of $b and $a.

It was benchmarked against the same thing done using a Schwartzian Transform for directories of various number of files up to 10,000. In all test it outperformed the ST (go figure). The performance was only measured in time to complete the check, no check for system impact was done while each was running.

Anyone interested in the bencmark code and results, just /msg me.

#!/usr/bin/perl -w use strict; printf "%s\n", (sort{ (-M $b) <=> (-M $a) } glob("*"));

Replies are listed 'Best First'.
Re: Print the oldest file in a directory.
by Aristotle (Chancellor) on Oct 31, 2002 at 18:50 UTC
    Note that glob '*' won't honour dotfiles. And why sort in the first place when you just want the oldest file? Using the convenient List::Util module you can emulate the structure of a Schwartzian Transform without sorting in this case:
    use List::Util qw(reduce); opendir DIR, "."; print @{ reduce { $a->[1] < $b->[1] ? $a : $b } map { -f $_ ? [$_, (stat _)[9]] : () } readdir DIR }->[0], $/; closedir DIR;
    And without a module:
    opendir DIR, "."; my ($oldest, @file) = map { -f $_ ? [$_, (stat _)[9]] : () } readdir D +IR; closedir DIR; while(my $cur = shift @file) { $oldest = $cur if $oldest->[1] > $cur->[1]; } print $oldest->[0], $/;

    Makeshifts last the longest.

•Re: Print the oldest file in a directory.
by merlyn (Sage) on Oct 30, 2002 at 20:21 UTC
      Yeah, it dosen't make sense to me either. I had already written the little one liner when someone here mentioned using an ST instead. For the exact same reason you stated above. I am checking the mod time of the same file at a minimum of 2 times, maybe more if the next file makes it out of the <=> operation.

      Please keep in mind, this is the first time I have ever used an ST. It is pretty much copied directly from http://www.5sigma.com/perl/schwtr.html.

      Here is the benchmark code I used to test it with the results. The directory had 16,108 files in it. Let me know what you think.

      #!/usr/bin/perl -w use strict; use Benchmark; timethese(100, { 'chad' => \&chad, 'swartz' => \&st,}); sub chad { sort{ (-M $b) <=> (-M $a) } glob("*"); } sub st { map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [$_, -M] } glob('*'); }

      Here are the results of the benchmark:

      Benchmark: timing 100 iterations of chad, swartz... chad: 118 wallclock secs (56.91 usr + 47.25 sys = 104.16 CPU) @ + 0.96/s (n=100) swartz: 1515 wallclock secs (142.33 usr + 1044.36 sys = 1186.69 CP +U) @ 0.08/s (n=100)
        Methinks there is some kind of optimization going on. Perhaps perl knows that a sorted array in scalar (or void?) context is just the length of the array, and so the sort can be optimized away in the first case? Also, you really should take the glob out of the equation (it's an expensive operation and heavily skews the results of the benchmark). I get the ST being more than twice as fast with this (also you have '$a <=> $b' in one, and '$b <=> $a' in the other & BTW I have about 63 files in the directory):
        use Benchmark; opendir(DIR, ".") or die "Acck: $!"; my @files = readdir DIR; closedir DIR; my $num_files = @files; print "$num_files\n"; timethese(-4, { 'chad' => \&chad, 'swartz' => \&st,}); sub chad { my @list = sort{ (-M $b) <=> (-M $a) } @files; } sub st { my @list = map { $_->[0] } sort { $b->[1] <=> $a->[1] } map { [$_, -M] } @files; }
Re: Print the oldest file in a directory.
by princepawn (Parson) on Oct 30, 2002 at 19:57 UTC
    `ls -lart | tail -1` # ;-)
    oh but this is Unix-specific. my bad