Perl: Capitalize First Letter of Each Word in a file name

Hi I'm trying to Capitalize First Letter of Each Word in a file name but keep the file extension lower case
I'm already removing the rubbish from the  name and I would like the results to look like this


my $Ext = "\.mp4|\.mkv|\.avi|\.srt";
while (my $file = <DATA>){

    my $new =  $file;
    $new =~ s/^(.+?(720|1080)p).+($Ext)$/$1$3/i;
    $new =~ s/\b(\w).*(?<=$Ext)/\U$1/g;
    print "new = $new\n";


Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

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.

How's this, Trev?:
    $new =~ s/(?<![A-Za-z])([a-z])/uc$1/ge;
or more concisely if you have Perl 5.10.0 or later:
    $new =~ s/[^A-Za-z]\K([a-z])/uc$1/ge;

Here's a demo of the latter regex from the Linux command line:
    echo | perl -pe 's/[^A-Za-z]\K([a-z])/uc$1/ge'

You could alternatively use this slightly more concise version:
      $new =~ s/[^A-Za-z]\K[a-z]/uc$&/ge;
but I think it may be slightly less efficient, performance wise.
An alternative non-substitution-regex version would be:
my @arr = map { /^s\d+e\d+$/ ? uc($_) : ucfirst $_ } split /\./, $file; # ucfirst each word (special case sXXeYY)
$arr[-1] = lc $arr[-1]; # change extension to lower-case
my $new = join '.', @arr; # rejoin string with fixed capitalization

Open in new window

Good point about the lower case extension, wilcoxon.  I somehow missed that requirement, and was working from the sample output supplied, i.e.:

Trev, here's my solution modified to handle lower case extensions:
    $new =~ s/(?<![A-Za-z])([a-z])(?=.+\.)/uc$1/ge;

And my 2nd & 3rd solutions in my 1st post were also incorrect because they didn't deal with the entire filename.  Not sure how my demo didn't show this problem, but I now see it fails to produce the output I showed.
Here's an alternative using \K:
    $new =~ s/(?:^|[^A-Za-z])\K([a-z])(?=.+\.)/uc$1/ge;
And a minor tweak of my code to handle any extra capital letters (your examples don't have any but just in case):
my @arr = map { /^s\d+e\d+$/ ? uc($_) : ucfirst lc $_ } split /\./, $file; # ucfirst each word (special case sXXeYY) after lower-casing
$arr[-1] = lc $arr[-1]; # change extension to lower-case
my $new = join '.', @arr; # rejoin string with fixed capitalization

Open in new window


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
trevor1940Author Commented:
Thanx for your help

Both soltions work hence dividing the points

I was thinking I might of needed to use fileparse to split the file name into parts

    my($name, $foo, $ext) = fileparse($file, qr/\.[^.]*/);
    print "namme $name, $ext\n";
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

From novice to tech pro — start learning today.