在Perl中删除90天以上的文件

时间:2016-06-08 17:34:02

标签: perl

我目前正在尝试删除目录中超过90天的所有文件。我能想到的唯一解决方案是比我认为必要的更多工作。有没有快速简便的方法来做到这一点?如果您使用此代码:

my $date=POSIX::strftime('%b%Y', localtime);
my $logDir = "/test/dir/"
my $dateDir = "$logDir/$date
#this directory contains files with the form of someName.date

4 个答案:

答案 0 :(得分:1)

您可以使用-M文件测试获取文件的年龄。来自-X

  

-M脚本开始时间减去文件修改时间,以天为单位。

其余的是获取文件列表。在这里,我使用opendirreaddir

use 5.012; # so readdir assigns to $_ in a lone while test
opendir(my $dh, $dateDir) or die "Can't open $dateDir directory: $!";
while (readdir($dh)) {
    my $file = "dateDir/$_";
    if (-f $file and -M $file > 90) {
        unlink $file or warn "Can't unlink $file: $!";
    }
}

上面的路径添加是必需的,因为readdir返回一个裸文件名,没有任何路径。您可以在实际删除之前包含各种测试。 (并且总是首先测试代码。)

在Perl 5.12之前的版本中,裸readdir 没有设置$_,这就是上面use 5.012的内容。对于这些版本我们需要做

opendir(my $dh, $dateDir) or die "Can't open $dateDir directory: $!";
while (my $file_nopath = readdir($dh)) {
    my $file = "$dateDir/$file_nopath";
    # same as above
}

我们可以在一行中读取目录(如果它不是太大),如果我们首先要包含所有文件的列表

my @filenames_relative = readdir($dh);

这是因为readdir返回的内容基于它所调用的上下文。由于此处的输出被分配给一个数组,所以它在列表上下文中被调用,它返回目录中所有条目的列表。

由于文件名是相对于该目录的,我们可以map将它们转换为完整路径

my @files = map { "$dateDir/$_" } readdir($dh);

此处readdir强加{em>列表上下文 map,因为该函数需要列表作为输入。

答案 1 :(得分:1)

这是使用File::Find::Rule的一种方式,因为它保留了完整的路径信息。比较的重要部分是-M $file > 90-M返回自上次修改文件以来的天数。

use warnings;
use strict;

use File::Find::Rule;

my $dir = '.';
my $days = 90;

my @files = File::Find::Rule->file()
                            ->maxdepth(1)
                            ->in($dir);

for my $file (@files){
    if (-M $file > 90){
        print "deleting $file\n";
        unlink $file or warn $!;
    }
}

注意maxdepth()方法说“不要遍历子目录"”。如果你想查看子目录,请将其设置为0

此外,如果要指定特定名称,可以添加name()方法,该方法将使用正则表达式并仅对这些文件进行操作。例如:name('*.2016*')

答案 2 :(得分:1)

如果我理解正确,那么您要删除目录/test/dir中超过90天的所有文件。我不明白my $dateDir = "$logDir/$date的用途,但这个单线解决方案会按照您的要求进行操作

$ perl -e 'unlink grep { -f and -M >= 90 } glob "/test/dir/*"'

答案 3 :(得分:0)

这是我在Perl中查找文件年龄的函数:

###########################################################################
# In: complete path to filename.
# Out: age in fractional days
sub getfileage
{my($fn)=@_;
my(@a,@b,$i,$j,$procname,$s,$t);

$procname="util2.pl:getfileage";

if (! -e $fn)
    {
    print "$procname ERROR: $fn does not exist\n";
    exit 1;
    }

my $age = -M $fn; # Returns age in days
$age=sprintf("%.2f",$age);

return $age; # getfileage
}

只需将其插入,然后传入文件名即可。 这对于可能偶然发现此问题的其他用户也很有用。