我想要一个目录和所有电子邮件(* .msg)文件,删除开头的'RE'。我有以下代码但重命名失败。
opendir(DIR, 'emails') or die "Cannot open directory";
@files = readdir(DIR);
closedir(DIR);
for (@files){
next if $_ !~ m/^RE .+msg$/;
$old = $_;
s/RE //;
rename($old, $_) or print "Error renaming: $old\n";
}
答案 0 :(得分:9)
如果您的./emails
目录包含以下文件:
1.msg
2.msg
3.msg
然后您的@files
看起来像('.', '..', '1.msg', '2.msg', '3.msg')
,但您的rename
想要'emails/1.msg'
,'emails/2.msg'
等名称。所以你可以{{3}重命名之前:
chdir('emails');
for (@files) {
#...
}
您可能也想查看chdir
返回值。
或者自己添加目录名称:
rename('emails/' . $old, 'emails/' . $_) or print "Error renaming $old: $!\n";
# or rename("emails/$old", "emails/$_") if you like string interpolation
# or you could use map if you like map
您可能希望使用chdir
组合目录读取和过滤:
my @files = grep { /^RE .+msg$/ } readdir(DIR);
甚至是这样:
opendir(DIR, 'emails') or die "Cannot open directory";
for (grep { /^RE .+msg$/ } readdir(DIR)) {
(my $new = $_) =~ s/^RE //;
rename("emails/$_", "emails/$new") or print "Error renaming $_ to $new: $!\n";
}
closedir(DIR);
答案 1 :(得分:5)
您似乎假设glob
- 就像行为而不是readdir
一样行为。
基础readdir
系统调用仅返回目录中的文件名,并包含两个条目.
和..
。这继续到Perl中的readdir
函数,只是为了更详细地介绍一下mu的答案。
或者,如果您正在收集数组中的所有结果,那么使用readdir
并没有多大意义。
@files = glob('emails/*');
答案 2 :(得分:2)
如前所述,由于您期望的路径和脚本使用的路径不同,您的脚本会失败。
我建议使用更透明的用法。对目录进行硬编码不是一个好主意,IMO。正如我在有一天学到的那样,我制作了一个脚本来改变一些原始文件,用硬编码的路径,我的同事认为这将是一个很好的脚本借用来改变他的副本。哎呀!
<强>用法:强>
perl script.pl "^RE " *.msg
即。正则表达式,然后是文件全局列表,其中路径相对于脚本表示,例如, *.msg
,emails/*.msg
甚至/home/pat/emails/*.msg /home/foo/*.msg
。 (多个可能的球)
使用绝对路径将使用户毫不怀疑他将影响哪些文件,并且还将使脚本可重用。
<强>代码:强>
use strict;
use warnings;
use v5.10;
use File::Copy qw(move);
my $rx = shift; # e.g. "^RE "
if ($ENV{OS} =~ /^Windows/) { # Patch for Windows' lack of shell globbing
@ARGV = map glob, @ARGV;
}
for (@ARGV) {
if (/$rx/) {
my $new = s/$rx//r; # Using non-destructive substitution
say "Moving $_ to $new ...";
move($_, $new) or die $!;
}
}
答案 3 :(得分:0)
我不知道正则表达式是否适合文件的指定名称,但是可以用以下一行完成:
perl -E'for (</path/to/emails*.*>){ ($new = $_) =~ s/(^RE)(.*$)/$2/; say $_." -> ".$new}
({say ...
非常适合测试,只需将其替换为rename $_,$new
或rename($_,$new)
)
<*.*>
读取当前目录中的每个文件($new = $_) =~
将以下替换保存在$new
中,并使$_
保持不变(^RE)
将此匹配项保存在$ 1(可选)中,只匹配开头为“ RE”的文件(.*$)
保存直到-包括行末($)在内的所有内容到$ 2 $2
中的字符串