2014-09-30 133 views
3

我需要在Perl中编写一个函数,在特定位置及其子目录(让我们称之为targetroot)下删除所有带有.rc后缀的文件。使用Perl,我如何查找和删除具有特定后缀的文件?

我在NT env工作,所以我不能使用系统命令,如findrm。 我已经厌倦了取消链接并找到选项,但没有管理。

我曾尝试是:

print "\n<<< Removing .rc files from $targetRoot\\20140929_231622 >>>\n"; 
my $dir = "$targetRoot\\20140929_231622"; 
find(\&wanted, $dir); 
sub wanted 
{ 
    unlink glob "*.rc"; 
} 

有人能告诉我该怎么办呢?

回答

3

你很近。 File::Find是这里工作的工具。尝试把你的wanted()为:

sub wanted { 
    # $_ set to filename; $File::Find::name set to full path. 
    if (-f and m/\.rc\z/i) { 
     print "Removing $File::Find::name\n"; 
     unlink ($File::Find::name); 
    } 
} 

首先尝试它当然没有取消链接,以确认你得到正确的目标。请记住,File::Find默认情况下会缓存目录结构。

+0

你的意思运行它这样呢? sub RemoveRC { \t print“\ n <<< \t从$ targetRoot \\ 20140929_231622 \t >>> \ n”中删除.rc文件; \t my $ dir =“$ targetRoot \\ 20140929_231622”;找到(\\想要的,$ dir); sub wanted {0} {0} {0}设置为文件名; $ File :: Find :: name设置为完整路径。 (m/\。rc \ Z /){ print“Removing $ File :: Find :: name \ n”; #unlink($ File :: Find :: name); } } } – user3720181 2014-09-30 11:31:11

+0

呃。我想是这样。良好的做法总是在运行某人代码时注释掉“危险的部分”。我很确定这会工作,但我只是互联网上的一些人。看看'unlink'看看它打印的内容是'会删除'。如果你感到快乐,那就把它放回去。 – Sobrique 2014-09-30 11:32:33

+0

@SinanÜnür:Windows文件名可能不包含控制字符,所以'\ z','\ Z'和'$'都很好。 – Borodin 2014-09-30 14:34:19

2

您需要修改wanted子程序:

sub wanted { /\.rc$/ && (unlink $File::Find::name or die "Unable to delete $_: $!") } 

File::Find文档

wanted功能

wanted()功能确实whateve r验证你想在每个 文件和目录。请注意,尽管名称不同,wanted() 函数是一个通用回调函数,并且不告诉 File::Find文件是否“需要”。事实上,其返回值 被忽略。

想要的函数不需要参数,而是通过一组变量来完成它的工作 。

`$File::Find::dir` is the current directory name, 

`$_` is the current filename within that directory 

`$File::Find::name` is the complete pathname to the file. 
0

尝试的代码块:

my $dir = "$targetRoot\\20140929_231622"; 
#subroutine call 
wanted($dir); 

#subroutine declaration 
sub wanted 
{ 
    my $result = $_[0]; 

    my @p = grep {-f} glob("$result\\*.rc"); 
    foreach my $file (@p) 
    { 
    print "Removing files $file from the directory $dir" . unlink($file) . "\n"; 

    } 
} 
+0

但我认为有一点关于递归遍历和通配符glob的东西有点儿脏。 – Sobrique 2014-09-30 12:49:38

1

Path::Class让事情更好一点:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Path::Class; 

run(@ARGV ? \@ARGV : ['.']); 

sub run { 
    my $argv = shift; 
    my $dir = dir(shift @$argv)->resolve; # will croak if path does not exist 
    $dir->recurse(callback => \&rm_if_rcfile); 
    return; 
} 

sub rm_if_rcfile { 
    my $entity = shift; 
    return if $entity->is_dir; 
    return unless $entity =~/[.] rc \z/ix; 
    print "$entity\n"; 
    return; # remove this line to actually delete 
    unless ($entity->remove) { 
     warn "'$entity' failed: $!\n"; 
    } 
} 
0
自定义 $targetRoot

除此之外,所有你需要做的是改变你的wanted子。

File::Find要求wanted节点(文件或目录),它发现您指定的根目录下。它会将基名(没有路径信息的裸文件名)放入$_,并将chdir放到包含它的目录中。

由于unlink的默认操作 - 如果您未传递参数 - 是要删除$_指定的文件,您只需检查它是一个文件并以.rc结尾。

此版本的wanted将为您做到这一点。

sub wanted { 
    unlink if -f and /\.rc\z/i; 
} 

这子程序很短,你不妨使用匿名子程序调用find。这是完整的版本,它也警告如果删除在任何文件上失败。

use strict; 
use warnings; 

use File::Find; 

my $targetRoot = 'C:\path\to\root'; 
my $dir  = "$targetRoot\\20140929_231622"; 

print qq{\n<<< Removing .rc files from "$dir" >>>\n}; 

find(sub { 
    -f and /\.rc\z/i and unlink or warn qq{Unable to delete "$File::Find::name"\n}; 
}, $dir); 
+0

@Zaid:谢谢。这将教会我直接输入代码到SO! – Borodin 2014-09-30 16:25:58

1

使用File::Find

use strict; 
use warnings; 
use autodie; 

use File::Find; 

my $dir = "targetRoot\\20140929_231622"; 

find(
    sub { 
     unlink if -f && /\.rc$/i; 
    }, 
    $dir 
); 

或者使用File::Find::Rule

use strict; 
use warnings; 
use autodie; 

use File::Find::Rule; 

my $dir = "targetRoot\\20140929_231622"; 

for (File::Find::Rule->file()->name('*.rc')->in($dir)) { 
    unlink; 
} 
相关问题