2016-10-11 100 views
1

Perl新手,只用了3次。我需要从父目录中删除文件和子文件夹,当它们超过一周的时间。我在使用-M之前删除了文件,但从未使用子文件夹。当我运行下面的详细信息时,没有文件从子文件夹中删除,并且子文件夹中存在一周以上的文件。对于子文件夹中的所有文件,测试消息显示'myAge'为零。不知道我错过了什么。任何援助将非常感激。使用Perl删除子文件夹和文件#

msg ("\n"); 
msg ("Start: \n"); 


my $parent = 'C:/temp/XYZ'; 
my ($par_dir, $sub_dir); 

opendir($par_dir, $parent); 
msg " parent is $parent \n"; 

while (my $sub_folders = readdir($par_dir)) { 
    next if ($sub_folders =~ /^..?$/); # skip . and .. 

    my $path = $parent . '/' . $sub_folders; 

    next unless (-d $path); # skip anything that isn't a directory 
    next unless (-M $subfolder < 7 ); 

    msg " subfolder is $sub_folders is old enough to delete \n"; 

    opendir($sub_dir, $path); 
    while (my $file = readdir($sub_dir)) { 

    # for testing  
    my $myAge = (-M $file) ; 
    msg " age ... $myAge __ file ... $file\n" ;  

     if (-M $file > 7 ) { 
     msg " going to delete this file... $file \n"; 
     } else { 
     msg " will keep this file not old enough $file\n"; 
     } 

    } 
    closedir($sub_dir); 
} 
closedir($par_dir); 
+0

'msg()'函数来自哪里? – simbabque

+0

除非(-M $ path <7);否则不应该为'next除非(-M $子文件夹<7);'为'而'-M $ file'是'-M“$ path/$ file”'? ['readdir'](http://perldoc.perl.org/functions/readdir.html)只返回一个文件或目录名(没有它的父目录)。 – PerlDuck

+0

msg()写入日志文件,对不起,因为没有引用早期 – Fondah

回答

0

如果这真的只是第三次使用Perl,那么恭喜!但也有一些问题,在您的代码:

  • 始终添加use strict;use warnings;到您的代码。这会警告(超出其他人)关于 未定义的变量并消除常见错误。
  • 您有一个错字$sub_folders$subfolderuse strict;use warnings;会显示。
  • readdir的返回值不包含父目录。该docs说:

    如果您打算filetest返回值了READDIR的,你最好预先准备 有问题的目录。否则,因为我们没有chdir, 它会测试错误的文件。

    我想这正是发生在这里。

我改变了一下你的代码,把目录放在文件名前面,它现在似乎工作。 我还写了一个msg函数,只是print是给定的参数。如果您拥有“真实”msg函数,则您将省略该 。

#!/usr/bin/env perl 

use strict; 
use warnings; 

sub msg 
{ 
    print @_; 
} 

msg("\n"); 
msg("Start: \n"); 

my $parent = 'C:/temp/XYZ'; 
my ($par_dir, $sub_dir); 

opendir($par_dir, $parent) or die "cannot opendir $parent: $!\n";; 
msg " parent is $parent \n"; 

while (my $sub_folders = readdir($par_dir)) { 
    next if ($sub_folders =~ /^..?$/); # skip . and .. 

    my $path = "$parent/$sub_folders"; 

    next unless (-d $path);    # skip anything that isn't a directory 
    next unless (-M $path < 7); 

    msg " subfolder is $sub_folders is old enough to delete \n"; 

    opendir($sub_dir, $path) or die "cannot opendir $path: $!\n"; 
    while (my $file = readdir($sub_dir)) { 

     # for testing 
     my $myAge = (-M "$path/$file"); 
     msg " age ... $myAge __ file ... $path/$file\n"; 

     if (-M "$path/$file" > 7) { 
      msg " going to delete this file... $path/$file \n"; 
     } else { 
      msg " will keep this file not old enough $path/$file\n"; 
     } 

    } 
    closedir($sub_dir); 
} 
closedir($par_dir); 

在这段代码中可以改进一些东西。

  1. 我不会检查目录中的修改时间并删除next unless (-M $path < 7);。 我的印象是,目录的属性(大小,时间)随意改变 - 至少我不能想出一个模式,但也许我太愚蠢了。
  2. 为加快速度,-X运算符(如-d,-M等)会缓存最后一个文件的结果。因此,而不是写

    next unless (-d $path); 
    next unless (-M $path < 7); 
    

    可以

    next unless (-d $path); 
    next unless (-M _ < 7); # the '_' means: get '-M' of $path 
    

    详见-X。基本上,-X一次获取给定文件的所有属性(如大小,类型,访问时间,修改时间等)。如果在后续调用中将下划线_作为 文件名传递,则会返回前一个调用的结果(具有实际文件名),并保存另一个(昂贵的)系统调用。

  3. 算法只考虑起始目录下的一个目录,即它不能递归地工作。 取决于你真正想要什么,这可能会也可能不会。

+0

谢谢你的细节非常有帮助! – Fondah

+0

@Fondah不客气。再一次:如果它真的是你的第三个剧本,那么你一定有一些天赋。用于显示[mcve]的+1。 – PerlDuck

1

假设你在* nix系统上..

有时更容易只是调用找到

find /foo/bar/ -type d -mtime +7 -exec rm -rf {} \; 

find /foo/bar/ -type f -mtime +7 -exec rm {} \; 

将删除所有7天前(d)irectories或(f) iles

+0

不错,但是在问题中加上'my $ parent ='C:/ temp/XYZ';'加上头部行中的_”... in Perl“_我假设OP正在寻找一个纯粹的Perl解决方案。 – PerlDuck

+0

OK,使用模块File:Find then。我想这是“cpanm安装文件:找到”,如果你有cpan减去安装。 (http://perldoc.perl.org/File/Find.html) –

+0

这将运行在Windows中,谢谢 – Fondah

相关问题