Search code examples
stringpowershellreplacetrim

How to remove all characters from multiple filenames after specified characters - Powershell


Forgive me if I explain poorly, I'm very new to PowerShell.

I'm trying clean up my media files and I'm trying to remove all characters after a specified string from multiple files with all sub directories of a directory.

The filename length will not be consistent. But the file types will. I need to exclude the extension from being removed as well.

So the files would look something like this:

  1. TVshow S01 E01 Title of episode.mp4
  2. LongerTVShow S03 E01 Title of episode.mp4

I want to remove everything after E01, while keeping E01

Result:

  1. TVshow S01 E01.mp4
  2. LongerTVShow S03 E01.mp4

I currently have a few other lines that are cleaning out characters I specify, for example finding periods and replacing them with spaces:

get-childitem -recurse | dir -Filter *.mp4 | Rename-Item -NewName { $_.BaseName.replace('.',' ') + $_.Extension }

That works well, as it will apply to all files in the directory. But you need to specify the character to replace.

I was then just going to use multiple instance of the command for E01, E02, E03 etc. In the same way I remove multiple stings like the code below:

get-childitem -recurse | dir -Filter *.txt | Rename-Item -NewName { $_.BaseName.replace('1080p','').replace('720p','').replace('HD','') + $_.Extension }

I was hoping to use something along the same lines, I've seen suggestions for trim or splitting but I can't seem to figure it out and I haven't been able to find anything.

Thanks for any answers!


Edit

I used the code by AdminOfThings and added that into what I have.

get-childitem -recurse |dir -Filter *.mp4 | Rename-Item -NewName { ($_.BaseName -creplace '(?<=S\d+ E\d+)\D.*') + $_.Extension }

So if anyone needs something like this in future, this will rename any .mp4 files in the directory and all sub directories it's run in. Specifically anything after E01, E02, E03 etc. Resulting in the following:

  1. TvShow S01 E04 title_of_show.mp4
  2. TvShow S08 E03Title_of_show.mp4

into:

  1. TvShow S01 E04.mp4
  2. TvShow S08 E03.mp4

Very specific but someone may find this useful.


Solution

  • You can do the following:

    Get-ChildItem -Recurse -Filter *.txt -File |
        Rename-Item -NewName { ($_.BaseName -creplace '(?<=S\d+ E\d+)\D.*') + $_.Extension }
    

    Explanation:

    The -creplace operator performs a case-sensitive regex match (-replace is case-insensitive) and then string replacement. If no string replacement is used, then the matched string is just replaced with empty string.

    The regex string is (?<=S\d+ E\d+)\D.*.

    • (?<=) is a positive lookbehind mechanism. This means that the current position in the string must have previous characters that match the lookbehind expression.
    • S\d+ matches literal s or S and one or more (+) digits (\d). In our case, only S is matched because we are using -creplace. The space after \d+ is a literal space.
    • E\d+ matches literal E and one or more digits.
    • \D matches a non-digit character. This is needed so that the lookbehind \d+ won't give back any digits. It allows us to be currently on a non-digit and know that we matched all previous digits.
    • .* matches any characters greedily until the end of the string.