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";
}
If your ./emails
directory contains these files:
1.msg
2.msg
3.msg
then your @files
will look something like ('.', '..', '1.msg', '2.msg', '3.msg')
but your rename
wants names like 'emails/1.msg'
, 'emails/2.msg'
, etc. So you can chdir
before renaming:
chdir('emails');
for (@files) {
#...
}
You'd probably want to check the chdir
return value too.
Or add the directory names yourself:
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
You might want to combine your directory reading and filtering using grep
:
my @files = grep { /^RE .+msg$/ } readdir(DIR);
or even this:
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);
You seem to be assuming glob
-like behavior rather than than readdir
-like behavior.
The underlying readdir
system call returns just the filenames within the directory, and will include two entries .
and ..
. This carries through to the readdir
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.
@files = glob('emails/*');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With