I am trying to clean up a rather large file system. I use the stat
function to obtain the modification time of each file.
According to perldoc -f stat
, the tenth element of the returned list is the last modified time in seconds since the epoch.
I use DateTime->from_epoch
and subtract DateTime->now
to calculate the age of the fule
#!/usr/bin/perl
use strict;
use warnings;
use DateTime;
my $now = DateTime->now();
#my $now = DateTime->now( time_zone => "America/New_York" );
$self->{dir} = '/tmp/test';
opendir(DIR, $self->{dir}) or die $@;
my @files = grep(/\.txt$/, readdir(DIR));
closedir(DIR);
for ( @files ) {
my $file = stat($self->{dir} . '/' . $_);
my $mtime = DateTime->from_epoch(epoch => $file->mtime);
#my $mtime = DateTime->from_epoch(epoch => $file->mtime, time_zone=> "America/New_York");
my $elapsed = $now - $mtime;
push(@{$self->{stale}}, {file => $self->{dir} . '/' . $_, mtime => $elapsed->in_units('minutes')}) if $elapsed->in_units('minutes') > 15;
push(@{$self->{remove}}, {file => $self->{dir} . '/' . $_, mtime => $elapsed->in_units('days')}) if $elapsed->in_units('days') > 10;
}
If I manually create test files and change the modification time, the result is off by 30 days
$ touch /tmp/test/test{100..104}.txt -d '-45 days'
$ perl MTIME.pm
$VAR1 = {
'mtime' => 15,
'file' => '/tmp/test/test100.txt'
}; $VAR1 = {
'mtime' => 15,
'file' => '/tmp/test/test104.txt'
}; $VAR1 = {
'mtime' => 15,
'file' => '/tmp/test/test103.txt'
}; $VAR1 = {
'mtime' => 15,
'file' => '/tmp/test/test101.txt'
}; $VAR1 = {
'mtime' => 15,
'file' => '/tmp/test/test102.txt'
};
I've tried DateTime
objects both with and without the time zone set with no difference in results.
$ touch /tmp/test/test{100..104}.txt -d '-45 days'
$ touch /tmp/test/test{105..110}.txt
$ ll /tmp/test
total 11
-rw-r--r-- 1 root root 0 Apr 3 19:31 test100.txt
-rw-r--r-- 1 root root 0 Apr 3 19:31 test101.txt
-rw-r--r-- 1 root root 0 Apr 3 19:31 test102.txt
-rw-r--r-- 1 root root 0 Apr 3 19:31 test103.txt
-rw-r--r-- 1 root root 0 Apr 3 19:31 test104.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test105.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test106.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test107.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test108.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test109.txt
-rw-r--r-- 1 root root 0 May 18 19:30 test110.txt
Working solution:
#!/usr/bin/perl
use strict;
use warnings 'all';
use Data::Dumper;
my $self = bless { }, 'My::Class';
my @files = glob '/tmp/test/*.txt';
for (@files) {
my $days = int(-M $_);
my $mins = int((time - (stat $_)[9]) / 60);
my $item = {
file => $_,
days => $days,
minutes => $mins
};
push @{ $self->{remove} }, $item if $days > 10;
push @{ $self->{stale} }, $item if $mins > 15;
}
print Dumper $self;
Your question is hard to understand because you are writing an object-oriented module and then running it as a program. The code you show won't compile, mainly because $self
is never declared or defined. If you hope for useful answers then please post a complete program that we can run and that demonstrates the problem that you are asking about
I can't try your program and see the problem for myself, but there are two obvious improvements to make
It is much easier to make a call to glob
than to open and read a directory, remove the files that you don't want, and rebuild the path to each file by adding back the directory
You can use the built-in -M
operator to discover the age of a file in floating-point days
I've written this, which creates an empty object in class My::Class
and adds data to it. It includes the ideas I''ve talked about, but like your own code provides no output. Hopefully you will understand how to interpret this into your own structure
The only problem you may have is that the mtime
fields are floating-point days. You may want to apply int
or POSIX::ceil
depending on what those values are used for
use strict;
use warnings 'all';
my $self = bless { }, 'My::Class';
my @files = glob '/temp/text/*.txt';
for my $file ( @files ) {
my $age = -M $file;
if ( $age >= 10.0 ) {
my $item = {
file => $file,
mtime => $age,
};
push @{ $self->{remove} }, $item;
push @{ $self->{stale} }, $item if $age >= 15.0;
}
}