Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Perl to rename files in a directory

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";
}
like image 567
Johnathan1 Avatar asked Dec 09 '11 19:12

Johnathan1


2 Answers

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);
like image 85
mu is too short Avatar answered Oct 13 '22 05:10

mu is too short


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/*');
like image 42
ephemient Avatar answered Oct 13 '22 07:10

ephemient