2014-09-30 29 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; 
} 
相關問題