Home > Back-end >  How to remove part of file name using a regex expression?
How to remove part of file name using a regex expression?

Time:10-28

I have a bunch of files names as such:

Belinda Carlisle - Mad About You-Xmdtjwmr9zq.mp4
Air Supply - All Out of Love-Jwdzeumnrmi.mp4
Blue Savannah Song - Erasure-Wxoutwk8jv8.mp4
Breathe - How Can I Fall (1988)-Pwz4erdjzra.mp4

I would like to be able to trim out the suffix of random characters. I got some help with formulating a regex, and I slapped together a two-liner in PowerShell, and it works. The only caveat is that I have to first filter by the regex before piping it to 'rename-item', otherwise, it adds two extensions to the filename like Belinda Carlisle -Mad About You.mp4.mp4 for the filenames that are 'clean' - aka without the extraneous suffix.

Can this be done another way so that I don't have to filter by matching regex and achieve the same thing? Not being nitpicky, just curious.

Here's the expression I cobbled together.

Get-ChildItem $targetpath -file | 
where-object {$_.name -match "-[a-z\d] (?=\.[^.] $)"} | 
ForEach-Object {
Rename-Item -Path $_.FullName -NewName ('{0}{1}' -f ($_.Name -replace "-[a-z\d] (?=\.[^.] $).*","$1"), $_.Extension )
}

CodePudding user response:

Your regex can be simplified to just this.

Clear-Host
(@'
Belinda Carlisle - Mad About You-Xmdtjwmr9zq.mp4
Air Supply - All Out of Love-Jwdzeumnrmi.mp4
Blue Savannah Song - Erasure-Wxoutwk8jv8.mp4
Breathe - How Can I Fall (1988)-Pwz4erdjzra.mp4
'@) -replace '-[\w]([^.] )'

# Results
<#
Belinda Carlisle - Mad About You.mp4
Air Supply - All Out of Love.mp4
Blue Savannah Song - Erasure.mp4
Breathe - How Can I Fall (1988).mp4
#>

CodePudding user response:

Offering an alternate solution to RegEx, you can use the string methods against the BaseName property then concatenating the result to the Extension.

Get-ChildItem $targetpath -Filter '*-*-*' -File | 
    Rename-Item -NewName { $_.BaseName.Substring(0,$_.BaseName.LastIndexOf('-'))   $_.Extension }

CodePudding user response:

  • As js2010 suggests, you can simplify your task by operating only on the .BaseName property of each input file, re-appending the filename extension after any potential transformation with ( $_.Extension)

  • It is both conceptually simpler and more efficient to use a delay-bind script block in your Rename-Item call, which allows piping input directly to it.

  • If a given file's name happens to be "clean" already, Rename-Item will - fortunately - be a quiet no-op; that is, if the -NewName argument is the same as the current file name, no action is taken.

Get-ChildItem $targetpath -File |
  Rename-Item -NewName { ($_.BaseName -replace '-[a-z\d] $')   $_.Extension } -WhatIf

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

  • Related