Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Mass file renaming

by interstellar (Initiate)
on Nov 07, 2005 at 14:57 UTC ( [id://506358]=perlquestion: print w/replies, xml ) Need Help??

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

Most worthy monks

My first post here so apologies as required in advance... I've run into a problem mass-renaming files, using some data internal to the file for the new name. I've tried looking at lots of rename stuff and the mass rename thread. here goes:

my @files=<c:/Storage/*.csv>; #Reads all csv files foreach(@files){ $newname=(extract some data from the file here) $success=rename $oldname,$newname; }
The error message I get is 'permission denied'. But, if I have "old.txt" file in the same dir and execute a simple $success=rename "old.txt","new.txt"; then it works ok.

If I change: @files=<c:/Storage/*.csv>; to @files=<c:/Storage/*.txt>; then it doesn't.

I've used Stat::lsMode to get the permissions -rw-rw-rw.

Very and increasingly confused, please help.

edit (broquaint): added <code> tags

Replies are listed 'Best First'.
Re: Mass file renaming
by Aristotle (Chancellor) on Nov 07, 2005 at 15:08 UTC

    There’s not much to guess the problem from in your post.

    First, I’m not sure about the privilege system on Windows, but in Unix, renaming requires write permissions on the directory, not the file, so you may want to check that. However, I don’t believe that’ll turn out to have been the problem.

    Second, do you have some actual examples of $oldname and $newname values from the rename that fails? Without those, it’s going to be very difficult to guess at your problem.

    Makeshifts last the longest.

      The data sample is currently stored on my C:/temp local drive. Admin, User, Everyone, System permissions are all Full Control.

      I have chdir to C:/Temp/Storage and verified by cwd.

      $oldfile name is typically location.csv ie "Langden Brook.csv"

      $newfile name is typically 573796RSst.csv

      What I find difficult to get my head around is that I can rename a file in the same dir so long as the filextension is not the one referenced in the foreach(@files) where the filehandle is say all csv files in the dir.

      Thanks again.

        You didn’t answer my question. I didn’t want to know what you think is in the variables; that’s just programming by coincidence. 99% of the bugs I encounter are due to variables containing things are than what I expected they would. Put an actual warn "$newfile $oldfile" if not $success; or some such in your code and make sure you know what the variables contain.

        Makeshifts last the longest.

Re: Mass file renaming
by swampyankee (Parson) on Nov 07, 2005 at 15:18 UTC

    I'm sure that you closed the file before you tried to rename it, because Windows gets cranky when one tries to rename or delete an open file.

    You did close it before renaming, didn't you?

    emc

      Hi,

      The file is closed, but the routine is still within a:

      foreach(@files); loop

      I don't know if this implements a lock of the files in the dir? If so, is it escapable?

      thanks for your contribution.

        It may have if you got @files by something like:

        opendir($dh, "$working_directory" @files = grep { /\.csv$/i } readdir($dh)

        and didn't close the directory. I know rmdir doesn't work on Windows if the directory being deleted is open somewhere; Windows may prevent writing the directory if it's still "open" by opendir.

        On the other hand...if you got the names by some other means, I'll admit being stumped.

        emc

Re: Mass file renaming
by Perl Mouse (Chaplain) on Nov 07, 2005 at 15:09 UTC
    • Does $newname contain what you think it contains?
    • Do you have write permission in the directory $oldname is in?
    • Do you have write permission in the directory $newname is going to be?
    Perl --((8:>*
      Yes, yes and yes...hmmm. Thanks for your contribution.
Re: Mass file renaming
by revdiablo (Prior) on Nov 07, 2005 at 15:47 UTC

    Looking at the other Monks' questions and your responses, I get the feeling there's something being missed along the way here. It's probably time to reduce your code down to a small, self-contained example that shows the problem, and post that entire small example. You might narrow it down yourself by doing this, but if not, then at least we have a full example we can go by to help you.

      Please find code as below. I'm a bit of a noob, so it should all either be easy enough or commented. RSVP if there's anything needs explanation.
      #!usr/bin/perl -w-T #ABOUT # Objective: renames all .csv files (from MS Excel) in a given #directory to <StationNumber><Parameter>.csv where <StationNumber> and #<Parameter> are taken from the file contents. #DETAIL # Abstracts relevant information from a file, re-names the file to #(typically): #<GaugeRefNo>REev.csv for tipping-bucket rainfall gauges. #<GaugeRefNo>RSst.csv for storage rainfall gauges. #CODE use strict; use diagnostics; use Cwd; my %renamefiles=(); my $renamefiles; my @keys=(); my $key; { my $files; my @files=<c:/Storage/*.csv>; #Reads all csv files foreach(@files) { my $open=$_; #Read current file to process from array my $string; #Slurp file line by line my $gaugeref; my $gaugeparam; my $currentdir; my $newdir; my $chaff; my $result; my $newname; my $oldname; ######TODO - Read $param from file contents # my $param="REev"; #For tipping bucket raingauges my $param="RSst"; #For storage raingauges # my $param="SG"; #For stage (level) ###### my $extension="csv"; #Strip filename to "/" in path $newdir=$_;$chaff=chop($newdir) while substr($newdir,length($n +ewdir)-1)!~/\//; chdir $newdir; #PARSE IN open(INFILE,"<", $open) or die "Couldn't open $open $!"; print "Opened $open \n"; while(<INFILE>) #Loop through lines { $string=$_; # GET STATION NUMBER if (lc($string)=~ /(gauge ref|station number)/) { my $station=$string; chomp $station; $chaff=chop($station) while substr($station,le +ngth($station)-1)=~/\D/; #drop chaff $result.=chop($station) while substr($station, +length($station)-1)=~/\d/; #append hits $gaugeref=reverse($result); next; }; }; close $open; $result="";#Clear $result.=chop($open) while substr($open,length($open)-1)!~/\// +;#read filename from path until encounters / $oldname=reverse($result); $newname="$gaugeref$param.$extension"; print "Old:$oldname\nNew: $newname\n"; %renamefiles=($oldname=>$newname); @keys=sort keys %renamefiles; foreach $key(sort keys %renamefiles) { if (!(-w $oldname)) {print "$oldname is not writeable\n";} else{ use Stat::lsMode; my $mode = file_mode($oldname); print "Filemode is $mode\n"; renamefile("$key","$renamefiles{$key}"); }; }; }; }; ######SUBS###### sub renamefile{ my $oldname=shift; my $newname=shift; my $success=""; print qq{Attempting to rename $oldname to $newname\n}; $success=rename $oldname, $newname; if ($success){print "Changed $oldname to $newname\n"} else {print "Failed to rename $oldname to $newname $!\n";exit}; };
      Thanks in for any help.

        This isn't quite what I had in mind when I said small example, but I guess it'll do. One thing I see right away is that you're not closing the file after you open it. As previously mentioned, Windows doesn't like to rename open files. Where you have:

        close $open;

        You should have:

        close INFILE;
Re: Mass file renaming
by b10m (Vicar) on Nov 07, 2005 at 18:12 UTC

    Maybe slightly off-topic, but I assume you use a MS Windows environment. Wasn't (isn't) a DOS shell capable of doing something like this?

    C:\Storage> rename *.csv *.txt

    Perl is awesome, but sometimes a little shell command could be easier.

    Then again, you seem to "extract some data from the file", and I bet Perl comes in handy there ;-)

    --
    b10m

    All code is usually tested, but rarely trusted.
      I'm light on Perl, but almost ethereal when it comes to DOS Scripting.

      It seems the file was not closed afterall, my simple sintax (simptax?) was wrong. Swampyankee you were right on there early on, but thanks to all for your contributions. Works a treat now!

      Worship, worship...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://506358]
Approved by blue_cowdawg
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-04-26 04:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found