How to find all files in a directory with a specific mtime

S

schms

Hi

I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

I was wondering, if anyone has a smarter solution:


use strict;
use File::Find;
use Time::Local;
use Date::Calc qw(Add_Delta_Days Today);

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;

###
### get today
###

my ($YEAR, $MONTH, $DAY) = Today();


###
### get past date
###

my ($PYEAR, $PMONTH, $PDAY) = Add_Delta_Days($YEAR, $MONTH, $DAY,
-$DAYS );


my $epoche_pastdate_start = timelocal(0, 0, 0, $PDAY, $PMONTH-1,
$PYEAR-1900);
my $epoche_pastdate_end = timelocal(59, 59, 23, $PDAY, $PMONTH-1,
$PYEAR-1900);


find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

my $epoche_mtime = (stat($File::Find::name))[9];

if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {

system("ls -al $File::Find::name");
}



I thank you for your comments.


Stefan
 
P

Paul Lalli

schms said:
Hi

I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

You have not at all explained what is "poor" about this solution. Is
it inefficient? Does it produce incorrect results? Is the code too
difficult to understand?

It's difficult to suggest an improvement when we don't know how the
current solution is lacking.
I was wondering, if anyone has a smarter solution:


use strict;
use File::Find;
use Time::Local;
use Date::Calc qw(Add_Delta_Days Today);

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;

###
### get today
###

my ($YEAR, $MONTH, $DAY) = Today();


###
### get past date
###

my ($PYEAR, $PMONTH, $PDAY) = Add_Delta_Days($YEAR, $MONTH, $DAY,
-$DAYS );


my $epoche_pastdate_start = timelocal(0, 0, 0, $PDAY, $PMONTH-1,
$PYEAR-1900);
my $epoche_pastdate_end = timelocal(59, 59, 23, $PDAY, $PMONTH-1,
$PYEAR-1900);

There's no reason for any of this.
find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

return unless -f and /\.ds$/;
my $epoche_mtime = (stat($File::Find::name))[9];

if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {

my $mtime_days = -M;

if ($mtime_days >=8 and $mtime_days < 9) {
system("ls -al $File::Find::name");

print "$File::Find::name\n";

Paul Lalli
 
B

Ben Morrow

Quoth "schms said:
Hi

I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

I was wondering, if anyone has a smarter solution:


use strict;

Good... you also want

use warnings;
use File::Find;

Do you need to recurse into directories (are there directories to
recurse into)? If not, something like

grep { <check timestamp> } glob '*.ds';

would probably be easier.
use Time::Local;
use Date::Calc qw(Add_Delta_Days Today);

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;

###
### get today
###

my ($YEAR, $MONTH, $DAY) = Today();


###
### get past date
###

my ($PYEAR, $PMONTH, $PDAY) = Add_Delta_Days($YEAR, $MONTH, $DAY,
-$DAYS );


my $epoche_pastdate_start = timelocal(0, 0, 0, $PDAY, $PMONTH-1,
$PYEAR-1900);
my $epoche_pastdate_end = timelocal(59, 59, 23, $PDAY, $PMONTH-1,
$PYEAR-1900);

I was going to suggest using -M, but it seems you specifically want just
the one day; and something like -M > 8 && -M <= 9 will be offset by the
current time-of-day.
find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

You can just test $_ here, as above, whice is clearer; and you need to
escape the .

return unless /\.ds$/;
my $epoche_mtime = (stat($File::Find::name))[9];

I would always use File::stat here, 'cos I don't like magic numbers.
if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {

I found this test confusing: when I first read it, I thought it was
wrong. I would probably have $epoche_pastdate_end be a whole day later
(rather than one second shy of a day) and then test it with <.
system("ls -al $File::Find::name");

I don't really like calling ls, but it's probably the easiest way to get
what you want. You don't need -a though: you're providing the list of
filenames.

I would probably build a list and use xargs, just for efficiency
(untested):

# outside the sub
my @names;

# here
push @names, $File::Find::name;

# after sub

open my $LS, '|-', xargs => ls => '-l'
or die "can't fork xargs: $!";

$, = $\ = "\n"; # or pass the -0 option to xargs and use \0

print $LS @names;

close $LS or die "xargs failed: $!";

Ben
 
S

schms

Hi Paul

The code works but it is a bit complicated. So I thought, there must
be a smarter way to do it.

Your input:

(..)

if ($mtime_days >=8 and $mtime_days < 9) ..

(..)

My first idea was to use this solution, but it does not work as one get
also files with modification time of (today - 9).


Thanks.


Stefan



Paul said:
schms said:
Hi

I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

You have not at all explained what is "poor" about this solution. Is
it inefficient? Does it produce incorrect results? Is the code too
difficult to understand?

It's difficult to suggest an improvement when we don't know how the
current solution is lacking.
I was wondering, if anyone has a smarter solution:


use strict;
use File::Find;
use Time::Local;
use Date::Calc qw(Add_Delta_Days Today);

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;

###
### get today
###

my ($YEAR, $MONTH, $DAY) = Today();


###
### get past date
###

my ($PYEAR, $PMONTH, $PDAY) = Add_Delta_Days($YEAR, $MONTH, $DAY,
-$DAYS );


my $epoche_pastdate_start = timelocal(0, 0, 0, $PDAY, $PMONTH-1,
$PYEAR-1900);
my $epoche_pastdate_end = timelocal(59, 59, 23, $PDAY, $PMONTH-1,
$PYEAR-1900);

There's no reason for any of this.
find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

return unless -f and /\.ds$/;
my $epoche_mtime = (stat($File::Find::name))[9];

if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {

my $mtime_days = -M;

if ($mtime_days >=8 and $mtime_days < 9) {
system("ls -al $File::Find::name");

print "$File::Find::name\n";

Paul Lalli
 
S

schms

Ben said:
Good... you also want

use warnings;


Do you need to recurse into directories (are there directories to
recurse into)? If not, something like

grep { <check timestamp> } glob '*.ds';

would probably be easier.



I know, that File:Find is recursivly, but the directory does not have
any subdirectories.


I was going to suggest using -M, but it seems you specifically want just
the one day; and something like -M > 8 && -M <= 9 will be offset by the
current time-of-day.


That is korrect (above).


find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

You can just test $_ here, as above, whice is clearer; and you need to
escape the .

return unless /\.ds$/;
my $epoche_mtime = (stat($File::Find::name))[9];

I would always use File::stat here, 'cos I don't like magic numbers.
if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {

I found this test confusing: when I first read it, I thought it was
wrong. I would probably have $epoche_pastdate_end be a whole day later
(rather than one second shy of a day) and then test it with <.


The system command is there just for debuging purposes....

system("ls -al $File::Find::name");

I don't really like calling ls, but it's probably the easiest way to get
what you want. You don't need -a though: you're providing the list of
filenames.

I would probably build a list and use xargs, just for efficiency
(untested):

# outside the sub
my @names;

# here
push @names, $File::Find::name;

# after sub

open my $LS, '|-', xargs => ls => '-l'
or die "can't fork xargs: $!";

$, = $\ = "\n"; # or pass the -0 option to xargs and use \0

print $LS @names;

close $LS or die "xargs failed: $!";

Ben

--
You poor take courage, you rich take care:
The Earth was made a common treasury for everyone to share
All things in common, all people one.
'We come in peace'---the order came to cut them down.[[email protected]]
 
J

John W. Krahn

schms said:
I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

I was wondering, if anyone has a smarter solution:


use strict;
use File::Find;
use Time::Local;
use Date::Calc qw(Add_Delta_Days Today);

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;

###
### get today
###

my ($YEAR, $MONTH, $DAY) = Today();


###
### get past date
###

my ($PYEAR, $PMONTH, $PDAY) = Add_Delta_Days($YEAR, $MONTH, $DAY,
-$DAYS );


my $epoche_pastdate_start = timelocal(0, 0, 0, $PDAY, $PMONTH-1,
$PYEAR-1900);
my $epoche_pastdate_end = timelocal(59, 59, 23, $PDAY, $PMONTH-1,
$PYEAR-1900);


( my $epoche_pastdate = localtime time - 8 * 24 * 60 * 60 ) =~
s'\d+:\d+:\d+'\d+:\d+:\d+';

find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );

my $epoche_mtime = (stat($File::Find::name))[9];

if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {


if ( $epoche_mtime =~ $epoche_pastdate ) {

system("ls -al $File::Find::name");
}


John
 
J

John W. Krahn

schms said:
I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

time should be 19.7.06)) and which end on *.ds.

As I am not expert in terms of perl, I found only the following poor
solution.

I was wondering, if anyone has a smarter solution:


use strict;
use File::Find;

my $DIR = '/aaaaa/bbbb/ccccc';
my $DAYS = 8;


[ SNIP ]

###
### get past date
###


( my $epoche_pastdate = localtime time - $DAYS * 24 * 60 * 60 ) =~
s'\d+:\d+:\d+'\d+:\d+:\d+';

find (\&my_func, $DIR);

sub my_func {

return unless -f;

return unless ( $File::Find::name =~ /.ds$/ );


return unless -f and /\.ds\z/;

my $epoche_mtime = (stat($File::Find::name))[9];


my $epoche_mtime = localtime( ( stat )[ 9 ] );

if ( $epoche_mtime >= $epoche_pastdate_start && $epoche_mtime
<= $epoche_pastdate_end ) {


if ( $epoche_mtime =~ $epoche_pastdate ) {

system("ls -al $File::Find::name");
}


John
 
D

Dr.Ruud

schms schreef:
I have to write a perl program which finds all files in a directory
with mtime (modification time)

of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06, so
the file's modification

#!/usr/bin/perl
use strict ;
use warnings ;

use IO::All ;

my $path = "$ENV{HOME}/dev/perl" ;

printf "%s%8d%3d %s\n"
, $_->uid, $_->size, -M $_->name, $_->filename
for sort {$b->mtime <=> $a->mtime}
io($path)->filter( sub
{
my $m = -M $_->name ;
8 <= $m and $m <= 9
})->all_files ;
 
S

schms

Hi Affijn

Your approach is totally new for me. I am going to study this.

Thanks a lot.

kind regards,

Stefan
 
D

Dr.Ruud

schms schreef:


[Don't top-post. Don't quote signatures nor disclaimers nor other tails.
Read the Posting Guidelines, that are posted here twice a week.]
Dr.Ruud:
schms:
I have to write a perl program which finds all files in a directory
with mtime (modification time)
of "today - 8 days" ( e.g. today is: 27.7.06, -8 days is: 19.7.06,
so the file's modification
Code:
[/QUOTE][/QUOTE]

Your approach is totally new for me. I am going to study this.[/QUOTE]

Revision, to make it look less daunting:

#!/usr/bin/perl
use strict ;
use warnings ;
use IO::All ;

use constant Days => 8 ;
my $filter = sub{my $m = -M $_->name; Days <= $m and $m <= Days+1} ;

my $path   = "$ENV{HOME}/dev/perl" ;

for (sort {$b->mtime <=> $a->mtime}
io($path)->filter($filter)->all_files)
{
printf "%s%8d%6.1f  %s\n"
,    $_->uid
,    $_->size
, -M $_->name
,    $_->filename
}


(IO:All doesn't have "mtime_days" yet...)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,996
Messages
2,570,237
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top