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

时间:2016-10-18 18:41:22

标签: 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);
        }
    }
}   

该函数将对第一个数组(@_)中的所有内容起作用,但除非第一个数组中的目录不包含空格,否则将无法在第二个数组中递归工作。

2 个答案:

答案 0 :(得分:1)

#!/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 spacesdir.with.spaces然后潜入 dir with spaces。那个目录已经消失了。您需要两个变量,一个用于旧名称 一个用于新的名称,然后在新名称上调用rm_space

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

我通过调用ls将呼叫替换为glob。优点是你不必关心 然后是名字中的空格。您的ls -1d dir with spaces/*必定已失败。

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

答案 1 :(得分:1)

要在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 ???