Perl:递归重命名所有文件和目录

时间:2010-03-31 23:28:42

标签: linux perl

我需要递归重命名每个文件和目录。我将空格转换为下划线,并将所有文件/目录名称设置为小写。如何使以下脚本在一次运行中重命名所有文件?目前,在转换所有文件/目录之前,需要多次运行脚本。代码如下:

#!/usr/bin/perl

use File::Find;

$input_file_dir = $ARGV[0];

sub process_file {
        $clean_name=lc($_);
        $clean_name=~s/\s/_/g;
        rename($_,$clean_name);
        print "file/dir name: $clean_name\n";
}
find(\&process_file, $input_file_dir);

3 个答案:

答案 0 :(得分:4)

您需要在传递的选项中指定bydepth => 1才能查找或致电finddepth。来自perldoc File::Find

  

bydepth

     

仅在报告所有条目后报告目录名称。输入点finddepth()是在{ bydepth => 1 }的第一个参数中指定find()的快捷方式。

但是,你还需要决定如何处理命名冲突,因为如果目标存在,重命名会破坏目标

#!/usr/bin/perl

use strict; use warnings;
use File::Find;

finddepth(\&process_file, $_) for @ARGV;

答案 1 :(得分:1)

如果您对其他方法持开放态度,那么这是一个Python解决方案

import os
for R,DIR,FILES in os.walk("/mypath",topdown=False):
    for file in FILES:
        newfile=file.lower().replace(" ","_")
        new_file_name=os.path.join(R,newfile)
        os.rename( os.path.join(R,file) , new_file_name)
    for dir in DIR:
        newdir=dir.lower().replace(" ","_")
        new_dir_name=os.path.join(R,newdir)
        os.rename( os.path.join(R,dir) , new_dir_name)

答案 2 :(得分:0)

您可以在遍历目录之前重命名文件。

find({
        preprocess => sub {
            for (@_) {
                my $oldname = $_;
                $_ = lc;
                s/\s/_/g;
                rename $oldname => $_;
            }
            return @_;
        },
        wanted => sub {
            print "$File::Find::name was already renamed\n";
        },
    },
    @dirs
);

或者你可以延迟重命名,直到发生遍历。

finddepth(sub {
        print "in $File::Find::dir, renaming $_\n";
        my $newname = lc;
        $newname =~ s/\s/_/g;
        rename $_ => $newname;
    },
    @dirs
);

您遇到的问题是因为

find找到目录"Abc Def"
find致电wanted("Abc Def") rename "Abc Def" => "abc_def"
find尝试输入"Abc Def",这不再存在了 所以下面的一切都没有得到处理