在Perl中删除超过90天的文件

在Perl中删除超过90天的文件,perl,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 使用-M文件

我目前正试图删除一个目录中所有超过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

使用
-M
文件测试可以在几天内获得文件的使用期限。从

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

剩下的就是获取文件列表

因为它似乎不需要递归,所以这里有一个带+

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

在Perl 5.12之前的版本中,bare
readdir
没有设置
$\uCode>,这就是上面的
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
根据调用它的上下文返回。因为它在这里的输出被分配给一个数组,所以它在列表上下文中被调用,并返回目录中所有条目的列表。由于文件名是相对于该目录的,我们还可以
立即将它们映射到完整路径中

my @files = map { "$dateDir/$_" } readdir($dh);
这里,列表上下文是由强加给
readdir
的,因为该函数需要一个列表作为输入

现在,根据您的条件取消链接
,或者对其进行筛选以获得就绪列表

my @files_to_delete = 
    grep { -f and -M > 90 } 
    map { "$dateDir/$_" }
    readdir($dh);
这些都可以在
map

my @files_to_delete = map { 
    my $f = "$dateDir/$_"; 
    ( -f $f  and -M $f > 90 ) ? $f : () 
} readdir($dh);
因为空列表
()
在返回列表中变平,实际上消失了


另一种方法是使用

这里有一种使用的方法,因为它保留了完整的路径信息。比较的重要部分是
-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*')

如果我理解正确,那么您希望删除目录
/test/dir
中所有超过90天的文件。我不明白我的$dateDir=“$logDir/$date
是做什么用的,但这一行解决方案将按您的要求执行

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

下面是我用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
}
只需插入该文件,并传入文件名。
这对其他可能遇到此问题的用户也很有用。

$file
将是
$dateDir
中的文件名,但您将其视为当前目录中的文件,这不起作用。要么将路径连接在一起,要么只使用
glob
。这正是我要找的。谢谢我的情况-M返回带小数点的值,例如:1.32366898148148。如何确保它只返回整数,以便与条件进行比较?thanks@WafieAli什么条件?我的支票大于90。为什么需要整数?如果你的支票是2,那么你的1.323…将小于2。它将大于1。Perl很神奇;你可以将浮点数与任何数字(甚至是字符串)进行比较没有问题。@stevieb和OP.btw中的一样,自从我了解了它的工作原理后,它就已经解决了。只是perl的新手。通过当前项目的实践任务进行自学。感谢帮助和关注buddy=)字符串
*.2016*
不是有效的正则表达式模式。我假设您想说通配符
$ perl -e 'unlink grep { -f and -M >= 90 } glob "/test/dir/*"'
###########################################################################
# 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
}