Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Renaming Directories Recursively

by blax (Sexton)
on Jul 22, 2001 at 00:49 UTC ( [id://98696]=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I am trying to rename every file and directory recursively. Here is my script:

#!/usr/bin/perl -w use strict; use File::Find; my $dir = shift; find (\&rem_space, $dir); sub rem_space { my ($new, $orig); $new = $orig = $_; $new =~ s/\s+/_/g; rename("$orig", "$new"); }
I get this error:
Can't cd to (dir/) A DIR : No such file or directory
for each directory that was at the first level. The directories on the first level get renamed but the rest do not. So find is trying to cd into the directory name before it was renamed.

So how do I rename directories recursively?

Thanks,
blax

Replies are listed 'Best First'.
Re: Renaming Directories Recursively
by wog (Curate) on Jul 22, 2001 at 01:20 UTC
    As others have mentioned, File::Find goes through all the entries of one directory, and then it goes to the subdirectory, which fails when the name changes. Fortunatly, File::Find has a workaround. You can either call find like:

    find({ bydepth => 1, wanted => \&rem_space }, $dir);

    or do this:

    finddepth(\&rem_space, $dir);

    These both cause File::Find to go through all the items inside a directory before handling the directory itself (as described in its documentation) so you can rename without messing it up.

Re: Renaming Directories Recursively
by rchiav (Deacon) on Jul 22, 2001 at 01:24 UTC
    I belive you need to tell it to process everything in the dir before it processes the dir itself. I *belive* this will force it to traverse to the end of the directory tree before it processes the lower level directories. To do this, call find with "bydepth => 1".
    find ({wanted => \&rem_space, bytedepth => 1}, $dir);
    That might do the trick.

    Hope this helps..
    Rich

    Rich is yet again wishing for the "Monks composing nodes that are identical to yours" feature..

Re: Renaming Directories Recursively
by John M. Dlugosz (Monsignor) on Jul 22, 2001 at 00:55 UTC
    Maybe renaming the dir confuses Find, which already thinks it knows the name of the directory to go next! You rename it, but then it can't cd to the old name!

    If that's the problem, do a post- rather than preorder traversal, or just note the (fully quallified) names of all the directories in a list in the find callback, and then rename them after find finishes.

    —John

Re: Renaming Directories Recursively
by simon.proctor (Vicar) on Jul 22, 2001 at 01:06 UTC
    I think you have the right idea but perhaps you should consider first building a directory index using file find and then renaming everything based on that.

    That way File::Find cannot get confused and you have a record of what you changed them from as well.

    Its only an idea though (hey its Saturday night and my 3rd can of beer :) )
Re: Renaming Directories Recursively
by synapse0 (Pilgrim) on Jul 22, 2001 at 01:19 UTC
    recursive loop...

    <psuedo-code>
    sub rename_dir { $curdir = shift; opendir($curdir) foreach $dir(readdir($curdir)) { next unless $dir is directory; &rename_dir($dir); # recurse rename($dir); } closedir(current dir) }
    </psuedo-code>
    something to that effect should work, i can't create a test run here, but i think the basics should be in that example..
    basically this follows the dir tree to the end, and then rename directories as it comes out of the loop.
    -Syn0

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 19:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found