Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

File::Find: Problem with renaming folders recursively

by larus (Acolyte)
on Mar 20, 2009 at 14:03 UTC ( #752041=perlquestion: print w/ replies, xml ) Need Help??
larus has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to use File::Find module to rename recursively certain chars in folder names in my directory tree. The code looks like this
#!/bin/perl use warnings; use strict; use File::Find; use File::Copy; my $path = $ARGV[0]; my $from = $ARGV[1]; my $to = $ARGV[2]; die "You must supply a full directory path" unless (-e $path && -d $pa +th); find(\&renamedir, "$path"); sub renamedir { next if -f $_; next if /^\./; my $new_name = $_; $new_name =~ s/$from/$to/g; chdir($File::Find::dir); move($_, $new_name) or die $!; }
When I e.g. call this script like this to convert a string "John" to "Matt"
C:\>Replace.pl "C:/Temp/" John Matt
I get an error saying that "Can't cd to (C:/Temp/) John : No such file or directory. So, it seems that the problem is that the script changes the folder name before it tries to cd into it. How could I tackle this problem? Thanks!

Comment on File::Find: Problem with renaming folders recursively
Select or Download Code
Re: File::Find: Problem with renaming folders recursively
by ELISHEVA (Prior) on Mar 20, 2009 at 14:08 UTC

    Why not just use full path names in your move command and avoid cd'ing altogether?

    Best, beth

Re: File::Find: Problem with renaming folders recursively
by bellaire (Hermit) on Mar 20, 2009 at 14:09 UTC
    I may be missing something, but don't you need to chdir into $path before you'll be able to descend into its subdirectories?

    Update: Ah, I did miss something, namely this passage from the documentation:
    You are chdir()'d to $File::Find::dir when the function is called, unl +ess no_chdir was specified.
Re: File::Find: Problem with renaming folders recursively
by Bloodnok (Vicar) on Mar 20, 2009 at 14:13 UTC
    Don't forget that that File::Find has chdired to the directory before &wanted() is called (you can't change the name of a directory whilst it is the current working directory) - I suspect that the postprocess & bydepth options may well be of use....

    A user level that continues to overstate my experience :-))
      Thanks for your replies. Anyway, I don't understand how should I modify this code. I'm very new to Perl.
Re: File::Find: Problem with renaming folders recursively
by zentara (Archbishop) on Mar 20, 2009 at 15:07 UTC
      I don't want to remove those dirs, I want to rename them.
        Well then, just take the code, take out the rmdir, and put in a rename. What? Are we supposed to write all your code for you? Just setup a test dir/subdir setup, and try renaming, with finddepth, instead of find. Also Google for "File::Find rename dirs"

        I'm not really a human, but I play one on earth My Petition to the Great Cosmic Conciousness
Re: File::Find: Problem with renaming folders recursively (File::Find::Rule)
by toolic (Chancellor) on Mar 20, 2009 at 16:59 UTC
    If you think File::Find is a little obscure, perhaps you should try the CPAN module File::Find::Rule instead. This might be one way to accomplish your goal:
    use warnings; use strict; use File::Find::Rule; my $path = $ARGV[0]; my $from = $ARGV[1]; my $to = $ARGV[2]; die "You must supply a full directory path" unless (-e $path && -d $pa +th); my @dirs = File::Find::Rule->directory() ->name("*$from*") ->in($path); for (@dirs) { my $orig = $_; s/$from/$to/g; rename $orig, $_ or die "Can not rename $orig to $_: $!"; }
      Thanks. This renames only the first directory in the directory tree, not the directories under the first directory. I'm lost.
      You're going to have to do a depth first search if you want to rename directories and their sub-directories, and File::Find::Rule doesn't seem to have an option for that. Though, I think you could sort the results by the number of directory separators (from greatest to least) -- yeah, that oughta work.
Re: File::Find: Problem with renaming folders recursively
by larus (Acolyte) on Mar 23, 2009 at 12:39 UTC
    I found a solution, this works fine:
    #!/bin/perl use warnings; use strict; use File::Find; use File::Copy; my $path = $ARGV[0]; my $from = $ARGV[1]; my $to = $ARGV[2]; die "You must supply a full directory path" unless (-e $path && -d $pa +th); finddepth(\&renamedir, "$path"); # find -> finddepth sub renamedir { return if -f $_; return if /^\./; my $new_name = $_; $new_name =~ s/$from/$to/g; move($_, $new_name) or die $!; }

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (12)
As of 2014-07-30 11:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (230 votes), past polls