2011-09-13 341 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});