使用Perl,如何查找和删除具有特定后缀的文件?

时间:2014-09-30 11:19:05

标签: perl

我需要在Perl中编写一个函数,删除在某个位置及其子目录下具有.rc后缀的所有文件(让我们称之为targetroot)。

我在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";
}

有人可以告诉我该怎么做吗?

6 个答案:

答案 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);