2011-09-13 247 views
0

我想使用File :: Find :: Rule遞歸地重命名目錄,例如。刪除每個發現額外的空間,但據我所知該模塊不會做finddepth並只重命名一個。有沒有辦法做到這一點。謝謝。如何遞歸地重命名目錄

use autodie; 
use strict ; 
use warnings; 
use File::Find::Rule; 

my $dir = 'D:/Test'; 

my @fd = File::Find::Rule->directory 
->in($dir); 

for my $fd (@fd) { 
    my $new = $fd; 

    $new =~ s/\s\s+/ /g; 

    print "$new\n"; 

    rename $fd, $new; 
} 
+0

的可能的複製[Perl的:遞歸重命名所有的文件和目錄],那麼該腳本會從基本目錄「測試」相對於工作目錄中的目錄名稱中刪除空格(http://stackoverflow.com/問題/ 2557199/perl-recursively-rename-all-files-and-directories) – amphetamachine

回答

3

你想先處理更深的結果,所以在處理反向列表。您只能重命名路徑的葉子部分;稍後你會到達更淺的部分。

use Path::Class qw(dir); 

for (reverse @fd) { 
    my $dir = dir($_); 
    my $parent = $dir->parent; 
    my $old_leaf = my $new_leaf = $dir->dir_list(-1); 

    $new_leaf =~ s/\s+/ /g; 

    if ($new_leaf ne $old_leaf) { 
     my $old_file = $parent->dir($old_leaf); 
     my $new_file = $parent->dir($new_leaf); 

     # Prevent accidental deletion of files. 
     if (-e $new_file) { 
     warn("$new_file already exists\n"); 
     next; 
     } 

     rename($old_file, $new_file); 
    } 
} 

回答到原來的問題:

我看不出FFR進場。

rename 'Test1/Test2/Test3', 'Test1/Test2/Dir3'; 
rename 'Test1/Test2', 'Test1/Dir2'; 
rename 'Test1', 'Dir1'; 

對於任意路徑,

use Path::Class qw(dir); 

my @parts1 = dir('Test1/Test2/Test3')->dir_list(); 
my @parts2 = dir('Dir1/Dir2/Dir3' )->dir_list(); 

die if @parts1 != @parts2; 

for (reverse 0..$#parts1) { 
    my $path1 = dir(@parts1[ 0..$_ ]); 
    my $path2 = dir(@parts2[ 0..$_ ]); 
    rename($path1, $path2); 
} 

或者,也許你想重命名所有的Test1到方向1,test2將方向2,和Test3的到DIR3,處理單子。

my %map = (
    'Test1' => 'Dir1', 
    'Test2' => 'Dir2', 
    'Test3' => 'Dir3', 
); 

my $pat = join '|', map quotemeta, keys %map; 

for (reverse @fd) { 
    my $o = $_; 
    my $n = $_; 
    $n =~ s{/\K($pat)\z}{$map{$1}}; 
    if ($n ne $o) { 
     if (-e $n) { 
     warn("$n already exists\n"); 
     next; 
     } 

     rename($o, $n); 
    } 
} 
+0

ikegami,非常感謝您的建議,但我正在尋找更通用的解決方案。我剛剛意識到我的例子是誤導性的,我對此非常抱歉。我正在編寫一個更大的腳本,用於根據File :: Find :: Rule組織文件和目錄,並且一次意識到我無法遞歸地大量重命名目錄 - 比如說大寫或小寫,或者替換找到的每個字符。如果這個模塊可以使用,我需要建議。 – thebourneid

+0

@thebourneid,那麼,如果你沒有準確定義問題,你爲什麼不開始解決這個問題呢? – ikegami

+0

我編輯了我的帖子並再次道歉。如果我沒有得到答案,就向我提供服務。我會測試你的建議。非常感謝。 – thebourneid

0

我有一個在目錄樹中遞歸執行操作的模塊。它雖然沒有能力在目錄上自己執行操作,但它只是稍作更新。我已經上傳了版本0.03的我的File::chdir::WalkDir,但直到它出現,它可以從它的GitHub repo安裝,現在可以使用您最喜愛的CPAN實用程序。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::chdir::WalkDir 0.030; 
use File::Copy; 

my $job = sub { 
    my ($name, $in_dir) = @_; 

    #ONLY act on directories 
    return 0 unless (-d $name); 

    my $new_name = $name; 
    if ($new_name =~ s/\s+/ /g) { 
    move($name, $new_name); 
    } 

}; 

walkdir('Test', $job, {'act_on_directories' => 1});