我目前正在尝试删除目录中超过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
答案 0 :(得分:1)
您可以使用-M
文件测试获取文件的年龄。来自-X
-M脚本开始时间减去文件修改时间,以天为单位。
其余的是获取文件列表。在这里,我使用opendir
和readdir
。
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
}
只需将其插入,然后传入文件名即可。 这对于可能偶然发现此问题的其他用户也很有用。