我需要在Perl中编写一个函数,删除在某个位置及其子目录下具有.rc
后缀的所有文件(让我们称之为targetroot)。
我在NT env工作,因此我无法使用find
或rm
等系统命令。
我已经厌倦了取消联系并找到选项,但没有管理。
我试过的是:
print "\n<<< Removing .rc files from $targetRoot\\20140929_231622 >>>\n";
my $dir = "$targetRoot\\20140929_231622";
find(\&wanted, $dir);
sub wanted
{
unlink glob "*.rc";
}
有人可以告诉我该怎么做吗?
答案 0 :(得分: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
默认情况下将递归目录结构。
答案 1 :(得分:2)
您需要修改wanted
子例程:
sub wanted { /\.rc$/ && ( unlink $File::Find::name or die "Unable to delete $_: $!" ) }
来自File::Find
文档
wanted
功能
wanted()
函数可以对每个函数进行任何验证 文件和目录。请注意,尽管名称为wanted()
function是一个通用的回调函数,并没有说明 如果文件是“想要的”,则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.
答案 2 :(得分:2)
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";
}
}
答案 3 :(得分: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;
}
答案 4 :(得分: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";
}
}
答案 5 :(得分: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);