Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Renaming a directory recursively 1

Status
Not open for further replies.

Tve

Programmer
May 22, 2000
166
FR
Hi,

I'm try to rename a directory recursively. I want to run a script at a directory and rename all subdirectories containning "-" to "_".

Eg: C:\temp
|_C:\temp\test\level-1
|_C:\temp\test\level-1\level-2

I use File::Find, which works find, but I get a problem once the directory has been modified. Here is the error:

Can't cd to (C:\temp\test/) level-1 : No such file or directory


I tried adding the no_chdir, but I didn't see a difference.

This is the code (still very preliminary):

use File::Find;

find (sub { \&process_file(), no_chdir}, "C:\\Temp\\test");


sub process_file {

if (($_ =~ /-/) && (-d $File::Find::name)) {

# Store passed directory name
my $tmpname = $_;

# Replace all "-" by "_"
$tmpname =~ s/-/_/g;

# Concatenate new name
my $newname = "$File::Find::dir/$tmpname";

# change $newname
my $rename = rename($File::Find::name, $newname) or die "Couldn't rename $_ to $newname: $!\n";
}
}



I understand the problem; but I don't know what to do.

Does anyone have an idee?

Thanks,

Thierry
 
It looks like find is making up a complete list of directories before it starts executing your sub. I can't really see a way around that. On the other hand, you don't really need to use find to get the desired result:

Code:
sub dir_dash_to_underscore {
	my $dir = shift;

	# find subdirectories of working directory
	opendir (DIR, $dir) || return;
	my @subdirs = grep {((-d "$dir/$_") && ($_ ne ".") && ($_ ne ".."))} readdir(DIR);
	closedir DIR;

	# recursively call each subdirectory, then rename it if there is a '-' in
	# its name
	my $s;
	foreach $s (@subdirs) {
		dir_dash_to_underscore("$dir/$s");
		if ($s =~ /-/) {
			my $newname = $s;
			$newname =~ s/-/_/g;
			rename ("$dir/$s", "$dir/$newname");
		}
	}

}

dir_dash_to_underscore("c:/temp/test");
 
Thanks sackyhack, this works fine.

Thierry.

 
On *nix systems you could just use a system call to a find command to do this. Add the -depth parameter to make it start out at the lowest level and work up (although you shouldn't necessarily need it).
Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top