我不是一个交易程序员,所以我只想把那个免责声明放在那里。并且可能有更好的方法来做到这一点,但这是我开始的方式,我想知道为什么这不起作用。
我有一个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);
}
}
}
该函数将对第一个数组(@_)中的所有内容起作用,但除非第一个数组中的目录不包含空格,否则将无法在第二个数组中递归工作。
答案 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 spaces
到dir.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 ???