在Perl中删除超过90天的文件
我目前正试图删除一个目录中所有超过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文件
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之前的版本中,barereaddir
没有设置$\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
}