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);
6
задан user305801 31 March 2010 в 23:28
поделиться

3 ответа

Вам нужно либо указать 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;
4
ответ дан 17 December 2019 в 04:44
поделиться

если вы открыты для других подходов, вот решение 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)
1
ответ дан 17 December 2019 в 04:44
поделиться

Вы можете переименовывать файлы перед перемещением по каталогу.

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 вызывает требует ("Abc Def")
rename "Abc Def" => "abc_def"
find пытается ввести "Abc Def" , которого больше не существует
, поэтому все, что внизу, не получается обработано

0
ответ дан 17 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: