perl函数将文件名和目录名中的所有空格替换为句点



我不是程序员,所以我只是想把免责声明放在那里。也许有更好的方法可以做到这一点,但这就是我开始的方式,我想知道为什么这不起作用。

我有一个perl函数,用于在文件名和目录中用句点替换空格:

sub rm_space {
    for(@_) {
    # for directory or file if it contains spaces, replace with periods
        chomp;
        if(m/^(.*(.(?=s).).*)$/) {
            $new = $_;
            $new =~ s/ /./g;
            move($_, $new);
        }
        if(-d) {
        # if $_ is a directory, list contents and repeat
            @arr = `ls -1d $_/*`;
            rm_space(@arr);
        }
    }
}   

该函数将处理第一个数组(@_(中的所有内容,但不会递归处理第二个数组,除非第一个数组中的目录尚未包含空格。

要在Perl中递归处理文件,请使用File::Find:

#!/usr/bin/perl
use warnings;
use strict;
use File::Find;
my %rename;
find(&spaces2dots, shift);
for my $old (sort { length $b <=> length $a } keys %rename) {
    rename $old, $rename{$old}
        or warn "Cannot rename $old to $rename{$old}.n";
}
sub spaces2dots {
    ( my $new = $File::Find::name ) =~ s{ (?!.*/)}{.}g;
    $rename{$File::Find::name} = $new;
}

文件按文件名长度排序,从最长的开始,每一步只替换最后一个/之后的空格,所以名为a b/c d/e f的文件被重命名为a b/c d/e.f,然后其父目录被重命名为a b/c.d,最后a b目录被重命名成a.b

为了完整起见,以下是我用于测试的Makefile:

run: clean
    mkdir 'a b' 'c d'
    mkdir 'a b'/'A B' 'a b'/'C D'
    mkdir 'a b'/'C D'/'e F'
    touch 'e f' 'a b'/'E F' 'a b'/'C D'/'e F'/'g H'
    40115711.pl .
    find
clean:
    rm -rf ???
#!/usr/bin/env perl
use strict;
use warnings;
sub rm_space
{
    foreach my $file_or_dir (@_) {
        my $with_dots = $file_or_dir;
        if ( $with_dots =~ tr/ /./ ) {
            # only called when replacement occurred
            rename( $file_or_dir, $with_dots );
        }
        if ( -d $with_dots ) {
            my @arr = glob("$with_dots/*");
            rm_space(@arr);
        }
    }
}
rm_space( glob("start_dir/*") );

您首先将目录从例如dir with spaces重命名为dir.with.spaces,然后深入dir with spaces。那个目录已经不见了。您需要两个变量,一个用于旧名称一个用于新名称,然后在新名称上调用rm_space

此外,强烈建议use strict;use warnings;避免常见错误(如打字错误(或未定义变量的使用(。

我将对ls的调用替换为对glob的调用。优点是你不必关心然后在名称中添加空格。您的ls -1d dir with spaces/*一定失败了。

我还使用了显式变量(而不是隐式$_(,因为有时很难弄清楚CCD_ 17实际包含的内容。

最新更新