Rename Directories

I have this part of a script to process all my txt files in the subdirectories and I know how to rename the filenames but how to tell the script for example to uppercase the containing folders - $dir1, $dir2, $dir3 or all of them with s/\b(\w)/\U$1/g; and without conflicting with the filename editing.
use strict; 
use warnings; 
use File::Find; 
use File::Spec;
 

find(\&d, "test"); 

sub d { 
       my $fn = $File::Find::name;
       
       my $dir1 = (File::Spec->splitdir($fn))[1];       
       my $dir2 = (File::Spec->splitdir($fn))[2];
       my $dir3 = (File::Spec->splitdir($fn))[3];

       while (<*.txt>) {
           my $filename = $_;
	  s/\b(\w)/\U$1/g;
           rename $filename, $_;
       }

}

Open in new window

thebourneidAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

wilcoxonCommented:
As long as you are running that on Windows, it will work fine as Windows is not case sensitive.  However, pretty much every other OS is (so it probably will interfere with file editing/renaming).

The simplest fix to avoid issues would be to add a second call to find after the first.  In one, you handle the directory renames and, in the other, you handle the file editing/renaming.

In general, you don't want to rename the directory in your sub d anyway as the script is currently chdir'd into the directory (which could cause problems).
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
thebourneidAuthor Commented:
wilcoxon,

I hate when I make hasty conclusions.
I've created a second sub and tested the script and the folders were renamed but later realized that also all the files in the folders were renamed also. I'm trying to rename only specific folders, in my case $dir3.
How to modify the script to do that task without touching the filenames.
use strict; 
use warnings; 
use File::Find; 
use File::Spec;


find(\&a, "test"); 

sub a { 
       my $fn = $File::Find::name;      
              
       my $dir1 = (File::Spec->splitdir($fn))[1];       
       my $dir2 = (File::Spec->splitdir($fn))[2];
       my $dir3 = (File::Spec->splitdir($fn))[3];
       
       
       $dir3 = $_;
       $dir3 =~ s/\b(\w)/\U$1/g;
       rename $dir3, $_;
      
}

Open in new window

0
wilcoxonCommented:
Your sub a is definitely renaming everything.  Do you want to rename $dir1 and $dir2 as well or just $dir3?

For a quick and dirty script to do this, I would do...
use strict; 
use warnings; 
use File::Find; 
use File::Spec;

my %dirs;
find(\&a, "test"); 

foreach my $dir1 (keys %dirs) {
    foreach my $dir2 (keys %{$dirs{$dir1}}) {
        foreach my $dir3 (keys %{$dirs{$dir1}{$dir2}}) {
            my $tmp = $dir3;
            $tmp =~ s/\b(\w)/\U$1/g;
            ## rather than the above, you could probably do this
            ## though it is slightly different if non-space sep.
            # $tmp = join ' ', split /\s+/, $dir3;
            rename $dir3, $tmp or die "could not rename $dir3 to $tmp: $!";
        }
        # repeat here for $dir2 if desired
    }
    # repeat here for $dir1 if desired
}

sub a { 
       my $fn = $File::Find::name;      
              
       my $dir1 = (File::Spec->splitdir($fn))[1];       
       my $dir2 = (File::Spec->splitdir($fn))[2];
       my $dir3 = (File::Spec->splitdir($fn))[3];

       # make sure we are 3 dirs deep
       return unless defined($dir3);

       # store the dir in a hash to avoid dupes
       $dirs{$dir1}{$dir2}{$dir3}++;
}

Open in new window

0
thebourneidAuthor Commented:
I decided to test the script, before doing something stupid with my directories, with some folder on my desctop named "dir" and I want to rename it to "dir_temp", but may be I'm missing something because nothing changes.
Am I counting the directories right - this should be $dir4
use strict;  
use warnings;  
use File::Find;  
use File::Spec; 
 
my %dirs; 
find(\&a, "C:/Users/Mimo/Desktop/dir/");  
 
foreach my $dir1 (keys %dirs) { 
    foreach my $dir2 (keys %{$dirs{$dir1}}) { 
        foreach my $dir3 (keys %{$dirs{$dir1}{$dir2}}) { 
		foreach my $dir4 (keys %{$dirs{$dir1}{$dir2}{dir3}}) { 
            my $tmp = $dir4; 
            $tmp =~ s/\b(\w)/\U$1/g;
            $tmp =~ s/dir/dir_temp/g; 	    
            ## rather than the above, you could probably do this 
            ## though it is slightly different if non-space sep. 
            # $tmp = join ' ', split /\s+/, $dir3; 
            rename $dir4, $tmp or die "could not rename $dir3 to $tmp: $!"; 
               } 
        # repeat here for $dir3 if desired 
            } 
    # repeat here for $dir2 if desired 
       }
   # repeat here for $dir1 if desired
}
 
sub a {  
       my $fn = $File::Find::name;       
               
       my $dir1 = (File::Spec->splitdir($fn))[1];        
       my $dir2 = (File::Spec->splitdir($fn))[2]; 
       my $dir3 = (File::Spec->splitdir($fn))[3]; 
       my $dir4 = (File::Spec->splitdir($fn))[4]; 
 
       # make sure we are 3 dirs deep 
       return unless defined($dir4); 
 
       # store the dir in a hash to avoid dupes 
       $dirs{$dir1}{$dir2}{$dir3}{$dir4}++; 
}

Open in new window

0
wilcoxonCommented:
I think you're doing it right.  My best advice is to add

print "dirs = ", join("\t", $dir1, $dir2, $dir3, $dir4), "\n";

to sub a.  First, I'd try putting them after the "return unless" and, if that doesn't work, try before the return.

I wonder if the E: gets counted as a dir or something?  I hardly ever code perl for Windows (I use CygWin if I'm on a Windows box).
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.