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

perl函数将文件名和目录名中的所有空格替换为句点,perl,Perl,我不是程序员,所以我只是想把免责声明放在那里。也许有更好的方法,但这是我开始的方式,我想知道为什么这不起作用 我有一个perl函数,用于将文件名和目录中的空格替换为句点: sub rm_space { for(@_) { # for directory or file if it contains spaces, replace with periods chomp; if(m/^(.*(.(?=\s).).*)$/) {

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

我有一个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);
        }
    }
}   
该函数将处理第一个数组(@_)中的所有内容,但不会递归地处理第二个数组,除非第一个数组中的目录不包含空格

#!/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
。那个目录已经不存在了。您需要两个变量,一个用于旧名称 一个用于新名称,然后对新名称调用
rm\u space

另外,强烈建议
使用strict
使用警告以避免常见错误(如打字错误
或使用未定义的变量)

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

我还使用了显式变量(与隐式的
$\uu
相反),因为有时很难理解 实际包含的内容

您首先将目录从例如
dir with spaces
重命名为
dir.with.spaces
,然后深入到
带空格的dir
。那个目录已经不存在了。您需要两个变量,一个用于旧名称 一个用于新名称,然后对新名称调用
rm\u space

另外,强烈建议
使用strict
使用警告以避免常见错误(如打字错误
或使用未定义的变量)

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

我还使用了显式变量(与隐式的
$\uu
相反),因为有时很难理解
实际包含的内容。

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


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


我真的看不出你的和我的有什么不同。。。这部分也不是问题,你说得对。但现在我想我发现了错误:在第一个
中,如果
将目录从
dir1
重命名为
dir.1
,然后使用旧名称执行
ls-1d dir1
。但那个目录已经不存在了。另外:
ls-1d dir 1
如果目录名中有空格,它将不起作用。你没有错误吗?我没有错误,是的,我也这么想。那么,第一步($新,$)不会立即生效吗?因为我认为当计算第二个if时,目录将被重命名并反映在第二个数组中。我假设情况并非如此,我想知道我是否能做到。魔法/隐藏/自动变量
$上的
-d
仍然有效,这一点没有改变。稍等。Is
$new=~$打字错误?我真的看不出你的和我的有什么区别。。。这部分也不是问题,你说得对。但现在我想我发现了错误:在第一个
中,如果
将目录从
dir1
重命名为
dir.1
,然后使用旧名称执行
ls-1d dir1
。但那个目录已经不存在了。另外:
ls-1d dir 1
如果目录名中有空格,它将不起作用。你没有错误吗?我没有错误,是的,我也这么想。那么,第一步($新,$)不会立即生效吗?因为我认为当计算第二个if时,目录将被重命名并反映在第二个数组中。我假设情况并非如此,我想知道我是否能做到。魔法/隐藏/自动变量
$上的
-d
仍然有效,这一点没有改变。稍等。Is
$new=~$输入错误?我以为我有,但我不知道你的例子似乎是最好的。谢谢你为我简化了它!我以为我有,但我不知道你的例子似乎是最好的。谢谢你为我简化了它!
#!/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;
}
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 ???