Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sorting dir output

5 views
Skip to first unread message

Craig Schneider

unread,
Apr 10, 2007, 7:19:40 AM4/10/07
to begi...@perl.org
Hi Guys

How could I exec a 'dir' command on a dos system and put the output in
an array, sort by date and the files that are older than 3 days be moved
into a folder called 'history'

Thanks

Craig

Jeff Pang

unread,
Apr 10, 2007, 9:04:23 AM4/10/07
to Craig Schneider, begi...@perl.org
Don't know much about dos.
But under unix you may got the files older than 3 days by this way,

chdir '/the/path';
@files = grep { time - (stat)[9] > 24*60*60*3 } glob "*";


2007/4/10, Craig Schneider <cra...@zdata.co.za>:

> --
> To unsubscribe, e-mail: beginners-...@perl.org
> For additional commands, e-mail: beginne...@perl.org
> http://learn.perl.org/
>
>
>


--
mailto: pa...@earthlink.net
http://home.arcor.de/jeffpang/

Ken Foskey

unread,
Apr 10, 2007, 9:10:19 AM4/10/07
to begi...@perl.org

Look at module File::Find this should be able to help you.

For a simplification of the other process you can use opendir function
to read the files in a directory one by one and then issue the stat as
in the other answer.

--
Ken Foskey
FOSS developer

ya...@kahanovitch.com

unread,
Apr 10, 2007, 10:02:31 AM4/10/07
to Craig Schneider, begi...@perl.org

Hi,

If you wish to select all files that are directly under given directory you can implement the following (in pure perl fashion):


sub numerically { $b <=> $a;}

$DIR = <Set in you directory>;

$THRESHOLD_IN_DAYS = 3;

my %time_to_file;
my $currTime = time();
#Store all file in hash with time as key.
for each my $file ( grep (-f,<*>)) {
my $time = stat($file)->mtime;
$time_to_file{$currTime - $time} = [] unless ( exists $time_to_file{$currTime - $time});
push @{$time_to_file{$currTime - $time}},$file;
}

#Sort by time from the new to the old
my @sorted = sort numerically keys(%time_to_job);

my $time_threshold_in_seconds = $THRESHOLD_IN_DAYS * 24 *3600

foreach my $atime (@sorted) {
if ($atime >= $time_threshold_in_seconds) {
foreach my $afile ($time_to_file{$atime}) {
print "$afile is older than $THRESHOLD_IN_DAYS lets delete it\n";
unlink($afile) or warn "Cannot delete $afile. $!";
}
}
}

Hope that helps

Yaron Kahanovitch

Hi Guys

Thanks

Craig

--

John W. Krahn

unread,
Apr 10, 2007, 10:27:27 AM4/10/07
to Perl Beginners
Craig Schneider wrote:
> Hi Guys

Hello,

> How could I exec a 'dir' command on a dos system and put the output in
> an array, sort by date and the files that are older than 3 days be moved
> into a folder called 'history'


# open the current directory
opendir my $dh, '.' or die "Cannot open '.' $!";

# get files older than three days
my @files = grep -M > 3, readdir $dh;

closedir $dh;

for my $file ( @files ) {
rename $file, "history/$file" or die "Cannot move '$file' $!";
}


John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall

Igor Sutton Lopes

unread,
Apr 10, 2007, 10:55:59 AM4/10/07
to John W. Krahn, Igor Sutton Lopes, Perl Beginners
Hi,

On Apr 10, 2007, at 3:27 PM, John W. Krahn wrote:

Craig Schneider wrote:
Hi Guys

Hello,

How could I exec a 'dir' command on a dos system and put the output in
an array, sort by date and the files that are older than 3 days be moved
into a folder called 'history'


# open the current directory
opendir my $dh, '.' or die "Cannot open '.' $!";

# get files older than three days
my @files = grep -M > 3, readdir $dh;

closedir $dh;

for my $file ( @files ) {
    rename $file, "history/$file" or die "Cannot move '$file' $!";
    }


You can also use File::Find::Rule for that:

<code>
use strict;
use warnings;

use File::Copy;
use File::Find::Rule;
use File::Spec;

my $basedir = "/Users/igorsutton/workspace";

sub move_file {
    move( $_[2], File::Spec->catdir( $basedir, 'history', $_ ) )
      or warn $!;
}

my $rule = File::Find::Rule->new;
$rule->directory()->name('trunk')->exec( \&move_file )->in($basedir);
</code>

--
Igor Sutton



PGP.sig

John W. Krahn

unread,
Apr 10, 2007, 11:40:42 AM4/10/07
to Perl Beginners

Did you test this? Where do you distinguish between files "older than 3 days"
and other files? Where is "name('trunk')" specified by the OP?

Igor Sutton Lopes

unread,
Apr 10, 2007, 12:55:00 PM4/10/07
to John W. Krahn, Igor Sutton Lopes, Perl Beginners
Sorry! I was testing and sent the last version -TextMate integrated with Mail.app- :-(

On Apr 10, 2007, at 4:40 PM, John W. Krahn wrote:

[...]
Did you test this?  Where do you distinguish between files "older than 3 days"
and other files?  Where is "name('trunk')" specified by the OP?

The correct answer:

<code>
use strict;
use warnings;

use File::Copy;
use File::Find::Rule;
use File::Spec;

my $basedir = "/Users/igorsutton/workspace";

sub move_file {

    # using -M is better than doing the calculation to obtain the difference
    # from now and three days ago.
    return unless -M $_ < 3;

    move( $_[2], File::Spec->catdir( $basedir, 'history', $_ ) )
      or warn $!;

    # cheat with File::Find::Rule returning an undefined value, to not waste
    # memory with unused data.
    return;
}

# we use the name '*' to remove the current directory.
File::Find::Rule->directory()->maxdepth(1)->name('*')->exec( \&move_file )
  ->in($basedir);
</code>

Sorry for the erroneous code before.

--
Igor Sutton



PGP.sig

John W. Krahn

unread,
Apr 10, 2007, 3:45:17 PM4/10/07
to Perl Beginners
Igor Sutton Lopes wrote:
> Sorry! I was testing and sent the last version -TextMate integrated
> with Mail.app- :-(
>
> On Apr 10, 2007, at 4:40 PM, John W. Krahn wrote:
>
>> [...]
>> Did you test this? Where do you distinguish between files "older
>> than 3 days"
>> and other files? Where is "name('trunk')" specified by the OP?
>
> The correct answer:
>
> <code>
> use strict;
> use warnings;
>
> use File::Copy;
> use File::Find::Rule;
> use File::Spec;
>
> my $basedir = "/Users/igorsutton/workspace";
>
> sub move_file {
>
> # using -M is better than doing the calculation to obtain the
> difference
> # from now and three days ago.
> return unless -M $_ < 3;

Why not just use the modified( '>3' ) rule?

> move( $_[2], File::Spec->catdir( $basedir, 'history', $_ ) )
> or warn $!;
>
> # cheat with File::Find::Rule returning an undefined value, to not
> waste
> # memory with unused data.
> return;
> }
>
> # we use the name '*' to remove the current directory.

> File::Find::Rule->directory()->maxdepth(1)->name('*')->exec ( \&move_file )


> ->in($basedir);
> </code>
>
> Sorry for the erroneous code before.

John

Chas Owens

unread,
Apr 10, 2007, 4:01:57 PM4/10/07
to John W. Krahn, Perl Beginners
On 4/10/07, John W. Krahn <kra...@telus.net> wrote:
> Igor Sutton Lopes wrote:
snip

> > return unless -M $_ < 3;
>
> Why not just use the modified( '>3' ) rule?
snip

There doesn't seem to be a performance issue either way:
Rate rule explict
rule 450/s -- -0%
explict 450/s 0% --

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark;


use File::Find::Rule;
use File::Spec;

my $basedir = "/home/cowens";

$a = 0;
$b = 0;

sub explict_wanted {


# using -M is better than doing the calculation to obtain the difference
# from now and three days ago.

$a++ unless -M $_ < 3;
}

sub rule_wanted {
$b++;
}

# we use the name '*' to remove the current directory.

my %subs = (
explict => sub {


File::Find::Rule->directory()->maxdepth(1)->name('*')

->exec(\&explict_wanted)->in($basedir);
},
rule => sub {


File::Find::Rule->directory()->maxdepth(1)->name('*')

->modified('>3')->exec(\&rule_wanted)->in($basedir);
}
);

Benchmark::cmpthese(-5, \%subs);

John W. Krahn

unread,
Apr 10, 2007, 4:54:50 PM4/10/07
to Perl Beginners
John W. Krahn wrote:
> Igor Sutton Lopes wrote:
>>
>>sub move_file {
>>
>> # using -M is better than doing the calculation to obtain the
>>difference
>> # from now and three days ago.
>> return unless -M $_ < 3;
>
> Why not just use the modified( '>3' ) rule?

Ok, modified( '>3' ) won't work because the file test rules don't take or use
arguments. However "return unless -M $_ < 3;" won't work correctly either as
it means that you are moving files that are *newer* not *older* than three
days. Also you are using the directory() rule which means that only
directorys are moved, not files.

Lost Sheep Of the Porn

unread,
Apr 14, 2007, 6:53:14 PM4/14/07
to
On Apr 10, 7:27 am, kra...@telus.net (John W. Krahn) wrote:
> Craig Schneider wrote:
> > Hi Guys
>
> Hello,
>
> > How could I exec a 'dir' command on a dos system and put the output in
> > an array, sort by date and the files that are older than 3 days be moved
> > into a folder called 'history'
>
> # open the current directory
> opendir my $dh, '.' or die "Cannot open '.' $!";
>
> # get files older than three days
> my @files = grep -M > 3, readdir $dh;
>
> closedir $dh;
>
> for my $file ( @files ) {
> rename $file, "history/$file" or die "Cannot move '$file' $!";
> }
>
> John

What does grep -M do? I couldn't find anything on either google or the
perlocs.


0 new messages