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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

transient rename errors

Status
Not open for further replies.

MrCBofBCinTX

Technical User
Dec 24, 2003
164
US
I am using this and several other similar functions to rename files and directories, changing spaces to underscores, remove repeated dashes, underscores, and changing to title case.

Code:
foreach my $file (@change_these) {
	next if $file =~ /^\.\.?$/;     # skip . and ..
	chomp $file;
	my $newfile = $file;
	if (($newfile =~ s/ /_/g)) {
		if (rename($file, $newfile)) {
			$count++;
			if ($verbose) {
				print "$file -> $newfile\n";
			}
		} else {
			warn("\nUnable to change filename:\n$file\n to:\n$newfile\n");
			$failed++;
		}
	}
}

code varies for each, but all similar.

Basically it all does its job, but I am getting unable to change errors which go away on second or third try.
I have a test set of file and directories I am testing against.
Does anyone see my error here?


Code:
foreach my $file (@change_these) {
	next if $file =~ /^\.\.?$/;     # skip . and ..
	chomp $file;
	my $newfile = $file;
	$newfile = lc $newfile;
	$newfile = ucfirst $newfile;
	$newfile =~ s/_([a-z])/_\u$1/g; #After underscore
	$newfile =~ s/-([a-z])/-\u$1/g; #After dash
	$newfile =~ s/ ([a-z])/ \u$1/g; #After space
	unless ($newfile eq $file) {
		if (rename($file, $newfile)) {
			$count++;
			if ($verbose) {
				print "$file -> $newfile\n";
			}
		} else {
			warn("Unable to change filename $file to $newfile");
			$failed++;
		}
	}
}
 
Can you show us examples of the unable to change errors and the test filenames in question perhaps?

Annihilannic.
 
OK.

These are the scripts to fill a test directory with these filenames and directory.
I ran the filename script manually in each directory since I wanted to test recursive changes.
Then I gtarred it all so I could repeat tests.

The problem seems to hit on the files with spaces in them.
there are actually three different scripts that fail in the same way. They all come from the same original though.

running the script another time gets the job done on failing renames. I made some changes to make reading the errors clearer. I need to collect those and post those (my previous errors ended up on one line. :)

Note: it looks like the forum is word wrapping a few

Code:
#!/bin/sh
# Test Files for Space to Underscore and Case Changer

#ALL CAPITALS
touch ALLCAPSNOSPACESORDASHESORUNDERSCORESNOPERIODSALLLETTERS
touch ALL.CAPS.NO.SPACES.NO.DASHES.NO.UNDERSCORES.WITH.PERIODS.ALL.LETTERS
touch 'ALL CAPS WITH SPACES NO DASHES OR UNDERSCORES NO PERIODS ALL LETTERS'
touch ALL_CAPS_NO_SPACES_NO_DASHES_WITH_UNDERSCORES_NO_PERIODS_ALL_LETTERS
touch ALL-CAPS-NO-SPACES-WITH-DASHES-NO-UNDERSCORES-NO-PERIODS-ALL-LETTERS
touch 'ALL-_.CAPS__-WITH _ __- -- SPACES-WITH---...--DASHES-WITH___ ____-UNDERSCORES-WITH....-PERIODS-ALL-LETTERS   -_'

#all lowercase
touch nocapsnospacesordashesorunderscoresnoperiodsallletters
touch no.caps.no.spaces.no.dashes.no.underscores.with.periods.all.letters
touch 'no caps with spaces no dashes or underscores no periods all letters'
touch no_caps_no_spaces_no_dashes_with_underscores_no_periods_all_letters
touch no-caps-no-spaces-with-dashes-no-underscores-no-periods-all-letters
touch 'no-_.caps__-with _ __- -- spaces-with---...--dashes-with___ ____-underscores-with....-periods-all-letters   -_'

#Mixed Case
touch MixedCapsNoSpacesOrDashesOrUnderscoresNoPeriodsAllLetters
touch Mixed.Caps.No.Spaces.No.Dashes.No.Underscores.With.Periods.All.Letters
touch 'Mixed Caps With Spaces No Dashes Or Underscores No Periods All Letters'
touch Mixed_Caps_No_Spaces_No_Dashes_With_Underscores_No_periods_All_Letters
touch Mixed-Caps-No-Spaces-With-Dashes-No-Underscores-No-Periods-All-Letters
touch 'Mixed-_.Caps__-With _ __- -- Spaces-With---...--Dashes-With___ ____-Underscores-With....-Periods-All-Letters   -_'

#Crazy Case
touch CrAzyCaPSNoSpaCesOrDashesOrUnDERSCOresNoPeriodsAllLetters
touch CrAzy.CaPS.No.SpaCes.No.Dashes.No.UnDERSCOres.With.Periods.All.Letters
touch 'CrAzy CaPS With SpaCes No Dashes Or UnDERSCOres No Periods All Letters'
touch CrAzy_CaPS_No_SpaCes_No_Dashes_With_UnDERSCOres_No_periods_All_Letters
touch CrAzy-CaPS-No-SpaCes-With-Dashes-No-UnDERSCOres-No-Periods-All-Letters
touch 'CrAzy-_.CaPS__-With _ __- -- SpaCes-With---...--Dashes-With___ ____-UnDERSCOres-With....-Periods-All-Letters   -_'

#Crazy Case With Numbers
touch C4rA22zyCaPSNoSpaCesOrDas654he978sOrUnDERSCOresNoPeriodsAll99Letters
touch C4rA22zy.CaPS.No.SpaCes.No.Das654he978s.No.UnDERSCOres.With.Periods.All.99Letters
touch 'C4rA22zy CaPS With SpaCes No Das654he978s Or UnDERSCOres No Periods All 99Letters'
touch C4rA22zy_CaPS_No_SpaCes_No_Das654he978s_With_UnDERSCOres_No_periods_All_99Letters
touch C4rA22zy-CaPS-No-SpaCes-With-Das654he978s-No-UnDERSCOres-No-Periods-All-99Letters
touch 'C4rA22zy-_.CaPS__-With _ __- -- SpaCes-With---...--Das654he978s-With___ ____-UnDERSCOres-With....-Periods-All-99Letters   -_'

and

Code:
#!/bin/sh

# Test Directories for Space to Underscore and Case Changer

#ALL CAPITALS
mkdir DIRALLCAPSNOSPACESORDASHESORUNDERSCORESNOPERIODSALLLETTERS
mkdir DIRALL.CAPS.NO.SPACES.NO.DASHES.NO.UNDERSCORES.WITH.PERIODS.ALL.LETTERS
mkdir 'DIRALL CAPS WITH SPACES NO DASHES OR UNDERSCORES NO PERIODS ALL LETTERS'
mkdir DIRALL_CAPS_NO_SPACES_NO_DASHES_WITH_UNDERSCORES_NO_PERIODS_ALL_LETTERS
mkdir DIRALL-CAPS-NO-SPACES-WITH-DASHES-NO-UNDERSCORES-NO-PERIODS-ALL-LETTERS
mkdir 'DIRALL-_.CAPS__-WITH _ __- -- SPACES-WITH---...--DASHES-WITH___ ____-UNDERSCORES-WITH....-PERIODS-ALL-LETTERS   -_'

#all lowercase
mkdir dirnocapsnospacesordashesorunderscoresnoperiodsallletters
mkdir dirno.caps.no.spaces.no.dashes.no.underscores.with.periods.all.letters
mkdir 'dirno caps with spaces no dashes or underscores no periods all letters'
mkdir dirno_caps_no_spaces_no_dashes_with_underscores_no_periods_all_letters
mkdir dirno-caps-no-spaces-with-dashes-no-underscores-no-periods-all-letters
mkdir 'dirno-_.caps__-with _ __- -- spaces-with---...--dashes-with___ ____-underscores-with....-periods-all-letters   -_'

#Mixed Case
mkdir DirMixedCapsNoSpacesOrDashesOrUnderscoresNoPeriodsAllLetters
mkdir DirMixed.Caps.No.Spaces.No.Dashes.No.Underscores.With.Periods.All.Letters
mkdir 'DirMixed Caps With Spaces No Dashes Or Underscores No Periods All Letters'
mkdir DirMixed_Caps_No_Spaces_No_Dashes_With_Underscores_No_periods_All_Letters
mkdir DirMixed-Caps-No-Spaces-With-Dashes-No-Underscores-No-Periods-All-Letters
mkdir 'DirMixed-_.Caps__-With _ __- -- Spaces-With---...--Dashes-With___ ____-Underscores-With....-Periods-All-Letters   -_'

#Crazy Case
mkdir DiRCrAzyCaPSNoSpaCesOrDashesOrUnDERSCOresNoPeriodsAllLetters
mkdir DiRCrAzy.CaPS.No.SpaCes.No.Dashes.No.UnDERSCOres.With.Periods.All.Letters
mkdir 'DiRCrAzy CaPS With SpaCes No Dashes Or UnDERSCOres No Periods All Letters'
mkdir DiRCrAzy_CaPS_No_SpaCes_No_Dashes_With_UnDERSCOres_No_periods_All_Letters
mkdir DiRCrAzy-CaPS-No-SpaCes-With-Dashes-No-UnDERSCOres-No-Periods-All-Letters
mkdir 'DiRCrAzy-_.CaPS__-With _ __- -- SpaCes-With---...--Dashes-With___ ____-UnDERSCOres-With....-Periods-All-Letters   -_'

#Crazy Case With Numbers
mkdir dIRC4rA22zyCaPSNoSpaCesOrDas654he978sOrUnDERSCOresNoPeriodsAll99Letters
mkdir dIRC4rA22zy.CaPS.No.SpaCes.No.Das654he978s.No.UnDERSCOres.With.Periods.All.99Letters
mkdir 'dIRC4rA22zy CaPS With SpaCes No Das654he978s Or UnDERSCOres No Periods All 99Letters'
mkdir dIRC4rA22zy_CaPS_No_SpaCes_No_Das654he978s_With_UnDERSCOres_No_periods_All_99Letters
mkdir dIRC4rA22zy-CaPS-No-SpaCes-With-Das654he978s-No-UnDERSCOres-No-Periods-All-99Letters
mkdir 'dIRC4rA22zy-_.CaPS__-With _ __- -- SpaCes-With---...--Das654he978s-With___ ____-UnDERSCOres-With....-Periods-All-99Letters   -_'
 
OK, now that I have clear error output:

Code:
Unable to change directory name:
 /home/chris101/Tools/test/DirMixed Caps With Spaces No Dashes Or Underscores No Periods All Letters
to:
/home/chris101/Tools/test/DirMixed_Caps_With_Spaces_No_Dashes_Or_Underscores_No_Periods_All_Letters

Unable to change directory name:
 /home/chris101/Tools/test/DirMixed-_.Caps__-With _ __- -- Spaces-With---...--Dashes-With___ ____-Underscores-With....-Periods-All-Letters   -_
to:
/home/chris101/Tools/test/DirMixed-_.Caps__-With_____-_--_Spaces-With---...--Dashes-With________-Underscores-With....-Periods-All-Letters___-_

Unable to change filename:
Mixed Caps With Spaces No Dashes Or Underscores No Periods All Letters
 to:
Mixed_Caps_With_Spaces_No_Dashes_Or_Underscores_No_Periods_All_Letters

Unable to change filename:
Mixed-_.Caps__-With _ __- -- Spaces-With---...--Dashes-With___ ____-Underscores-With....-Periods-All-Letters   -_
 to:
Mixed-_.Caps__-With_____-_--_Spaces-With---...--Dashes-With________-Underscores-With....-Periods-All-Letters___-_

etc.

However, upon looking into the directories and files, all has been changed appropriately.
I just checked all three using tree to verify after first and second run.

All are doing the job correctly, first time.

The error message seems to be the problem.
 
Great test data, might hang on to that for my own testing, thanks! :)

I ran the first version of your script against that test data and it worked fine, when I ran it a second time it didn't do anything.

All I did was add this to the beginning:

Code:
[gray]#!/usr/bin/perl -w[/gray]
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$verbose[/blue]=[fuchsia]1[/fuchsia][red];[/red]
[black][b]my[/b][/black] [blue]$count[/blue]=[fuchsia]0[/fuchsia][red];[/red]
[black][b]my[/b][/black] [blue]$failed[/blue]=[fuchsia]0[/fuchsia][red];[/red]
[black][b]my[/b][/black] [blue]@change_these[/blue][red];[/red]

[url=http://perldoc.perl.org/functions/opendir.html][black][b]opendir[/b][/black][/url][red]([/red]DIR, [red]"[/red][purple].[/purple][red]"[/red][red])[/red] || [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]can't opendir: [blue]$![/blue][/purple][red]"[/red][red];[/red]
[blue]@change_these[/blue] = [url=http://perldoc.perl.org/functions/readdir.html][black][b]readdir[/b][/black][/url][red]([/red]DIR[red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/closedir.html][black][b]closedir[/b][/black][/url] DIR[red];[/red]

That was under HP-UX with perl 5.8.0, what environment are you working in?

Annihilannic.
 
We cross-posted. I guess the note on perldoc -f rename rings true here: "Behavior of this function varies wildly depending on your system implementation."

Annihilannic.
 
OpenBSD -current

Yeah, I was wondering about rename myself.
An earlier version had problems with needing to be repeated, but that turned out to be a bad ordering of the various substitutions. Once I moved them around, that problem vanished.

At first I thought this problem was same sort, but its not.

The whole thing is much larger to select between only files or files and directories, recursive or not, quiet or not.
And to pick a directory to start at and match patterns to only change the right files and directories.
For example, "fix" mp4, wav and mp3 files
Or "fix" windows/DOS files with all those nasty spaces and all capital letters.

But, what I posted is really all that is hiccuping.

I want to get it all working and combine it into one nice module and command line script.

I've learned that use lots of comments lesson, but I'm only just starting to use testing. Seems like a good thing to do.
 
Can't help with the actual problem, but I would consider putting your test case data in a file (or as __DATA__) as a way of allowing you to refactor your tests more easily...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Although, if he had done that, he would not have discovered the rename feature that he seems to be encountering.

Annihilannic.
 
I tried using File::Copy, but that did not help.

I finally caught the problem, it had nothing to do with rename, I was failing to check for duplicates after matching files/directories to change. Easy enough to fix.

I did discover another problem with recursion, but that shouldn't be hard to fix either
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top