in reply to rename subdirectories

sub rename($) { my $path = $_[0]; #append a trailing / if it's not there if($path !~ /\/$/) { $path .= '/'; } #loop through the files contained in the directory for my $eachFile (glob($path.'*')) { #if the file is a directory if(-d $eachFile) { #pass the directory to the routine ( recursion ) rename($eachFile); } else { my @strings = split('/', $eachFile); my $fileName = $strings[$#strings]; my $filePath = '/'.join('/', @strings[2..$#strings-1]); system("mv $filePath/$fileName $filePath/\"YourNewNameHere\""); } } }#rename
This is adapted from a script of mine that browses a directory recursively and does something else to each file but it should work for you (or should be close enough - I have not tested it). The filename is made of the path to it plus its name. This name may identify a file or a directory. If it is a directory go in and do your job there first by renaming the files and then you rename the directory itself as well. If you don't follow this order, you'll end up trying to browse a directory that no longer exists (because you've read it's name but you've also renamed it before you tried to browse it).

That sample system call is one way of doing it and assumes you're using unix (or cygwin on windows). You can definitely change that or maybe use a Perl package for file handling if the OS is a problem.

Hope this helps!

Replies are listed 'Best First'.
Re^2: rename subdirectories
by andreas1234567 (Vicar) on Dec 04, 2007 at 13:31 UTC
    I have not tested it
    I wish you did because it does not work the way you expect, if at all.

    First, you redefine the perl built-in rename. So a call to rename would resolve to CORE::rename(), not the one you just wrote.

    Second, you use neither strict nor warnings, which would have indicated:

    Not enough arguments for rename at line 22, near "$eachFile)"
    since rename takes a list of two elements as input.

    Third, you're using a prototype. Don't. Read When to use Prototypes?, and I quote from a node written by tilly: Prototypes have many silent, nasty and unexpected side-effects..

    Last, and most importantly, it does not work (even after correcting the above errors):

    $ mkdir -p /tmp/654653 $ cd /tmp/654653 $ mkdir -p FOO/BAR $ mkdir -p FOO/TZE $ touch FOO/BAR/BANANA $ touch FOO/BAR/APPLE $ touch FOO/TZE/ORANGE $ perl 654653.pl mv: cannot stat `//654653.pl': No such file or directory mv: cannot stat `/BAR/APPLE': No such file or directory mv: cannot stat `/BAR/BANANA': No such file or directory mv: cannot stat `/TZE/ORANGE': No such file or directory mv: cannot stat `/654653/654653.pl': No such file or directory mv: cannot stat `/654653/FOO/BAR/APPLE': No such file or directory mv: cannot stat `/654653/FOO/BAR/BANANA': No such file or directory mv: cannot stat `/654653/FOO/TZE/ORANGE': No such file or directory
    I don't want to disencourage from sharing your code, I just wish you tested it first. A working solution to the original problem could be:
    use strict; use warnings; use File::Find; my $path = '.'; finddepth(\&pattern, $path); sub pattern { print "$_\n"; rename($_, lc($_)); } __END__
    --
    Andreas