• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 103
  • Last Modified:

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

"The.Best.TV.Show.S01E01.720p.Mkv"

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";
    
}

__DATA__
the.best.TV.show.s01e01.720p.crap.here.mkv
the.best.TV.show.s01e02.1080p.mp4
the.best.TV.show.s01e03.720p.mpg
the.best.TV.show.s01e04.720p.avi
the.best.tv.show.jpg

Open in new window

0
trevor1940
Asked:
trevor1940
  • 2
  • 2
2 Solutions
 
tel2Commented:
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 the.best.TV.show.s01e03.720p.mpg | perl -pe 's/[^A-Za-z]\K([a-z])/uc$1/ge'
The.Best.TV.Show.S01E03.720P.Mpg

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.
0
 
wilcoxonCommented:
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

0
 
tel2Commented:
Good point about the lower case extension, wilcoxon.  I somehow missed that requirement, and was working from the sample output supplied, i.e.:
  "The.Best.TV.Show.S01E01.720p.Mkv"

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;
0
 
wilcoxonCommented:
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

0
 
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


[code]
    my($name, $foo, $ext) = fileparse($file, qr/\.[^.]*/);
    print "namme $name, $ext\n";
[/code]
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now