Below is the sub routine I use to format audio files for my system. There's has to be a better way. If I send in a song like 01-21 stones.mp3, I get back 01. 21. Stones.mp3. Another, more annoying example is with a title that may have a date. 01-Up on the roof 10-21-1960.mp3 becomes 01. Up On The Roof 10. 21. 1960.mp3. I guess I'm okay with the idea that if I have a number in the title other than the track, I treat them all the same. It would just be nice if you folks can help me clean this up and maybe just treat the track separate from the title. Also, I set the ID3 tags/Flac tags from the filename. I don't depend on the tags to generate the file name.

Thanks in advance.

Code

sub FixFileName() { $oldfile = $file; # First make the filename all lowercase $file =~ tr/[A-Z]/[a-z]/; # Get rid of the underscores and make them spaces $file =~ s/_/ /g; # Get rid of double spaces $file =~ s/ / /g; # Make sure we have spaces on each side of dash $file =~ s/-/ - /g; # Make the first letter Uppercase if Alpha $file =~ s/^([a-z])/\u$1/; # Anything that follows the left paran to uppercase $file =~ s/\(([a-z])/\(\u$1/g; # Anything that follows the left bracket to uppercase $file =~ s/\[([a-z])/\[\u$1/g; # Anything that follows a period to uppercase $file =~ s/\.([a-z])/\.\u$1/g; # For every letter following a space make uppercase $file =~ s/ ([a-z])/ \u$1/g; # Anything that follows a dash to uppercase # Commented out - We have a space after a dash # $file =~ s/\-([a-z])/\-\u$1/g; # Get rid of double spaces $file =~ s/ / /g; # For those files that only have a space between track and title $file =~ s/([0-9]) ([0-9,A-Z,\(,\[])/$1\. $2/; # Get back to Track. Title if currently a number-space-dash $file =~ s/([0-9]) - ([0-9,A-Z,\(,\[])/$1\. $2/; # We no longer need the space on each side of the dashes we put in $file =~ s/ - /-/g; $file =~ s/-\./\./g; # Need to fix the extension (letter following a period is upper) $file =~ s/$\.Mp3/$\.mp3/; $file =~ s/$\.Flac/$\.flac/; # print $oldfile, " -> ",$file,"\n"; rename ( $oldfile, $file ) unless $oldfile eq $file; }

I'm trying to make the file names appear as ##. Title where the number is formatted as two digits with leading zero. The Title will be formatted with uppercase characters for each word following a space, bracket, paran or dash.

For example 01. The Song Name For The Year (It Must Be Good).mp3 02. This Way Too [Remastered].flac 03. Other Way-Off Names 'Encountered' [W/Other Help].mp3

I guess my intent for my original post is to just get better with regular expressions and reduce the lines of code. The function I posted is nearly the first thing I've tried as so its written like reg-ex 101 or intro to regular expressions :-)

Other useless info: My kids rip their discs to a local drive on their machines. I've installed MythTV with MythMusic. All of the media is brought into the single box. Too ensure I don't end up with duplicate files and everything is 'pretty,' I've been using the function to format the files. I could have made everything lower-case or upper-case but I decided to not do that in favor of something more formatted.

The season has created some delays on getting back to you. First, thanks for your input. I took the code you provided and below is my current process to 'standardize' my audio system. The structure for my files is: Artist/Album/Track. Title. I ran into some scenarios that were outside my original description. I also decided to run the directory names through the same code to ensure they were more controlled.

Again, you provided me with some pieces (particularly the boundary code) that I had not seen before. Like many things, I'll keep playing around with this as I encounter other situations. This script below is modifying files that are already in place. I've got another script that copies from a source to the destination. The source files are less structured and may need more attention than we are doing here.

$NewText =~ s/\b([a-z]+)\B/ucfirst(lc($1))/eg; #Boundary ends with a Number

In the first line the square brackets are not doing anything. The square brackets do not make a character class when using tr///. tr/// is not a regular expression like s/// and m// are. Leaving them in is not hurting anything but they are being treated as literal characters and not as a character class. But to make everything lower-case, use the lc() function:

$text = lc($text);

In the second line, it looks like you would be better using \d instead of \B as the end of pattern anchor. \d is digits 0-9. -------------------------------------------------

Thanks for the other tips. I did find one more issue with my code. For items containing characters like ˙, the next letter is uppercase. One example is Queensr˙Che. I'll work on that and see what I can come up with. I'll let you know what I come up with.