使用 Perl 重命名目录中的文件
我想要一个目录,对于所有电子邮件 (*.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";
}
I'd like to take a directory and for all email (*.msg) files, remove the 'RE ' at the beginning. I have the following code but the rename fails.
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";
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您的
./emails
目录包含这些文件:那么您的
@files
将类似于('.', '..', '1.msg' , '2.msg', '3.msg')
但您的重命名
想要像'emails/1.msg'
这样的名称,'emails/2.msg'
等。因此您可以重命名之前的 chdir
:您可能还想检查
chdir
返回值。或者自己添加目录名称:
您可能希望使用
grep< 组合目录读取和过滤/code>
:
甚至是这样:
If your
./emails
directory contains these files:then your
@files
will look something like('.', '..', '1.msg', '2.msg', '3.msg')
but yourrename
wants names like'emails/1.msg'
,'emails/2.msg'
, etc. So you canchdir
before renaming:You'd probably want to check the
chdir
return value too.Or add the directory names yourself:
You might want to combine your directory reading and filtering using
grep
:or even this:
您似乎假设
glob
类似的行为而不是readdir
类似的行为。底层的 readdir 系统调用仅返回目录中的文件名,并将包含两个条目
.
和..
。这会延续到 Perl 中的readdir
函数,只是为了提供有关 mu 答案的更多详细信息。或者,如果您无论如何都要收集数组中的所有结果,那么使用 readdir 就没有多大意义。
You seem to be assuming
glob
-like behavior rather than thanreaddir
-like behavior.The underlying
readdir
system call returns just the filenames within the directory, and will include two entries.
and..
. This carries through to thereaddir
function in Perl, just to give a bit more detail on mu's answer.Alternately, there's not much point to using
readdir
if you're collecting all the results in an array anyways.正如已经提到的,您的脚本失败是因为您期望的路径和脚本使用的路径不同。
我建议采用更透明的用法。 IMO,对目录进行硬编码不是一个好主意。有一天,当我制作一个脚本来更改一些原始文件并使用硬编码路径时,我了解到,我的一位同事认为这是一个很好的脚本,可以借用来更改他的副本。哎呀!
用法:
即正则表达式,然后是文件全局列表,其中路径表示与脚本相关的路径,例如
*.msg
、emails/*.msg< /code> 甚至
/home/pat/emails/*.msg /home/foo/*.msg
。 (可能有多个全局变量)使用绝对路径将使用户毫不怀疑他将影响哪些文件,并且还使脚本可重用。
代码:
As already mentioned, your script fails because of the path you expect and the script uses are not the same.
I would suggest a more transparent usage. Hardcoding a directory is not a good idea, IMO. As I learned one day when I made a script to alter some original files, with the hardcoded path, and a colleague of mine thought this would be a nice script to borrow to alter his copies. Ooops!
Usage:
i.e. regex, then a file glob list, where the path is denoted in relation to the script, e.g.
*.msg
,emails/*.msg
or even/home/pat/emails/*.msg /home/foo/*.msg
. (multiple globs possible)Using the absolute paths will leave the user with no doubt as to which files he'll be affecting, and it will also make the script reusable.
Code:
我不知道正则表达式是否适合文件的指定名称,但是可以用一行代码来完成:
perl -E'for (){ ($new = $_) =~ s/(^RE)(.*$)/$2/; say $_." -> ".$new}
(
say ...
很适合测试,只需将其替换为rename $_,$new
或rename($_,$new)
)<*.*>
读取当前目录中的每个文件($new = $_) = ~
将以下替换保存在$new
中并将$_
保持原样(^RE)
将此匹配项保存在 $1 中(可选),并仅匹配开头带有“RE”的文件(.*$ )
保存所有内容,直到并包括该行的末尾 ($) ->将匹配项替换为 $2$2
I don't know if the regex fits the specifig name of the files, but in one line this could be done with:
perl -E'for (</path/to/emails*.*>){ ($new = $_) =~ s/(^RE)(.*$)/$2/; say $_." -> ".$new}
(
say ...
is nice for testing, just replace it withrename $_,$new
orrename($_,$new)
)<*.*>
read every file in the current directory($new = $_) =~
saves the following substitution in$new
and leaves$_
as intact(^RE)
save this match in $1 (optional) and just match files with "RE" at the beginning(.*$)
save everything until and including the end ($) of the line -> into $2$2