Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am new Perl and programming and saw a snippet on here I thought I would try to fix to work for me, but its not working. What am I doing wrong? Any help would be greatly appreciated. For testing I wanted to change all files named "append" to "aPPend"
die("Cannot open /cdw/home_dir/s006258/MarketingDB/.") unless(opendir(DIR, "/cdw/home_dir/s006258/MarketingDB/")); #Print to new file die("Cannot open Log file to read from.") unless(open(FILES, ">List_of_files_changed.txt")); print "Reading from file\n"; #reading from file for my $file (readdir(DIR)) { if($file =~ /^append/) { print "$file\n"; $old=$_; s/^append/aPPend/; die "$_ already exists" if (-e $_); print "$old is old and $_ is new\n"; rename($old, $_) or die "Failed to rename\n"; } }
The output for the last print statemen gives me " is old and new is new" and says "Failed to rename". Thanks again...

Replies are listed 'Best First'.
Re: trying to rename files
by ikegami (Patriarch) on Jun 09, 2006 at 20:25 UTC
    • You keep using $_, but the file name is in $file.

    • readdir returns file names, not paths. You'll need to prepend the file names you pass to -e and rename with /cdw/home_dir/s006258/MarketingDB/.

    • Why do you hide your actions after your error messages? Instead of
      die(...) unless (action)
      use
      action or die(...)

    • You never write to your log.

    • foreach my $file (readdir(DIR))
      loads the entire list into memory, whereas
      while (defined(my $file = readdir(DIR)))
      reads one at a time.

    • You're very random in your use of parenthesises. Be consistent.

    Cleaned up code:

    #!/usr/bin/perl use strict; use warnings; use File::Spec (); my $dir = '/cdw/home_dir/s006258/MarketingDB'; my $log = 'List_of_files_changed.txt'; opendir(local *DIR, $dir) or die("Cannot open $dir.\n"); open(local *FILES, '>', $log) or die("Cannot open output file $log.\n"); while (defined(my $file = $filereaddir(DIR))) { next unless $file =~ /^append/; my $old = my $new = $file; $new =~ s/^append/aPPend/; $old = File::Spec->catfile($dir, $old); $new = File::Spec->catfile($dir, $new); die("Unable to rename $old: $new already exists.\n") if -e $new; rename($old, $new) or die("Unable to rename $old: $!\n"); print FILES ("$old renamed to $new\n"); }

    Updated.

    Update: 3rd point was backwards.

      I did that and still gives me the same output.... Is the "s/^append/aPPend/;" even relevant? How does it know what file to do a substitution against?
Re: trying to rename files
by philcrow (Priest) on Jun 09, 2006 at 20:40 UTC
    Maybe I'm missing something, but I can't see where $_ gets set to anything useful (which is probably a good thing overall). Where you have $_ I think you need to have $file instead, since you have named it in the for declaration. Then also change the s/// to operate on $file:
    $file =~ s/^append/aPPend/;
    If you omit the left hand side, the s/// will apply to $_, but as I mentioned, I don't think that's being set.

    Phil

      Thanks everyone it works perfectly...... Great to have such good resources like u guys on here... Great site...
Re: trying to rename files
by gellyfish (Monsignor) on Jun 09, 2006 at 20:39 UTC

    You don't get the full path of the file from readdir - you need to append the path to the filename before you do the rename.

    I'm also not sure what you think you are doing with the $_ - if you supplied use warnings you would be told about the problem.

    /J\

Re: trying to rename files
by bigmacbear (Monk) on Jun 09, 2006 at 20:45 UTC

    Looks like you're missing a couple of things here.

    1. You open a file for writing (">List_of_files_changed.txt") and then never use the associated file handle. Perhaps you intended to redirect one of your print statements using print FILES ..., but didn't.
    2. Within a for loop, if you specify a variable to be filled (as you do by specifying for my $file), $_ doesn't get filled in. Either use $file or $_, not both.

    Hope this helps.