~/shababsays/posts/Automatically-Rename-Subtitle-Files-to-Match-Video-Files-on-Windows home
← all posts

[PowerShell] Automatically Rename Subtitle Files to Match Video Files on Windows

Automatically Rename Subtitle Files to Match Video Files on Windows

If you have downloaded a TV series separately from its subtitle files, you may end up with something like this:

Plain text
Video:
24 (2001) - S02E02 - Day 2 900 A.M. - 1000 A.M. (1080p BluRay x265 ImE).mkv

Subtitle:
24.S02E02.1080p.BluRay.x264-SHORTBREHD.srt

The episode is the same, but the filenames are completely different.

Most media players work best when the subtitle filename is identical to the video filename:

Plain text
24 (2001) - S02E02 - Day 2 900 A.M. - 1000 A.M. (1080p BluRay x265 ImE).mkv
24 (2001) - S02E02 - Day 2 900 A.M. - 1000 A.M. (1080p BluRay x265 ImE).srt

Doing this manually for an entire season is annoying.

Fortunately, PowerShell can automatically match the files using the episode number such as S02E01, S02E02, S02E03, etc.

Before

Before

After

After


Method 1: Videos and Subtitles Are in the Same Folder

Suppose your folder contains:

Plain text
24 (2001) - S02E01 - ....mkv
24 (2001) - S02E02 - ....mkv
24 (2001) - S02E03 - ....mkv

24.S02E01.1080p.BluRay.x264-SHORTBREHD.srt
24.S02E02.1080p.BluRay.x264-SHORTBREHD.srt
24.S02E03.1080p.BluRay.x264-SHORTBREHD.srt

Open the folder in Windows File Explorer.

Click the address bar, type:

Plain text
powershell

and press Enter.

PowerShell will open directly inside that folder.


Step 1: Preview the Changes

Before actually renaming anything, I recommend checking what PowerShell intends to do.

Paste:

PowerShell
$videos=@{}; Get-ChildItem *.mkv | % { if($_.Name -match 'S\d{2}E\d{2}'){$videos[$matches[0]]=$_} }; Get-ChildItem *.srt | % { if($_.Name -match 'S\d{2}E\d{2}' -and $videos[$matches[0]]){"$($_.Name)  -->  $($videos[$matches[0]].BaseName).srt"} }

You should see output similar to:

Plain text
24.S02E01.1080p.BluRay.x264-SHORTBREHD.srt
-->
24 (2001) - S02E01 - Day 2 800 A.M. - 900 A.M. (1080p BluRay x265 ImE).srt

and:

Plain text
24.S02E02.1080p.BluRay.x264-SHORTBREHD.srt
-->
24 (2001) - S02E02 - Day 2 900 A.M. - 1000 A.M. (1080p BluRay x265 ImE).srt

Nothing is renamed yet.

This is only a preview.


Step 2: Rename Everything

If the preview looks correct, run:

PowerShell
$videos=@{}; Get-ChildItem *.mkv | % { if($_.Name -match 'S\d{2}E\d{2}'){$videos[$matches[0]]=$_} }; Get-ChildItem *.srt | % { if($_.Name -match 'S\d{2}E\d{2}'){$key=$matches[0]; if($videos[$key]){Rename-Item -LiteralPath $_.FullName -NewName ($videos[$key].BaseName+'.srt')}} }

That's it.

PowerShell will automatically turn:

Plain text
24.S02E02.1080p.BluRay.x264-SHORTBREHD.srt

into:

Plain text
24 (2001) - S02E02 - Day 2 900 A.M. - 1000 A.M. (1080p BluRay x265 ImE).srt

The .mkv and .srt filenames will now match.


How Does It Work?

The useful part is this pattern:

Plain text
S\d{2}E\d{2}

It searches the filename for standard TV episode identifiers such as:

Plain text
S01E01
S01E02
S02E14
S05E23

PowerShell then:

  1. Scans all .mkv files.
  2. Extracts their SxxExx episode numbers.
  3. Scans all .srt files.
  4. Finds the subtitle with the same episode number.
  5. Copies the video's filename.
  6. Changes only the extension to .srt.

This means the rest of the filenames can be completely different.

For example:

Plain text
My.Show.S03E07.1080p.WEB-DL-GROUP.srt

can still match:

Plain text
My Show (2024) - S03E07 - Episode Name (1080p x265).mkv

because both contain:

Plain text
S03E07

Method 2: Videos and Subtitles Are in Different Folders

If your files are arranged like this:

Plain text
D:\TV Shows\24\Season 2\

and:

Plain text
D:\TV Shows\24\Season 2\Subtitles\

use this version instead:

PowerShell
$videoFolder = "D:\TV Shows\24\Season 2"
$subtitleFolder = "D:\TV Shows\24\Season 2\Subtitles"

$videos = @{}

Get-ChildItem $videoFolder -Filter *.mkv | ForEach-Object {
    if ($_.Name -match 'S\d{2}E\d{2}') {
        $videos[$matches[0]] = $_
    }
}

Get-ChildItem $subtitleFolder -Filter *.srt | ForEach-Object {
    if ($_.Name -match 'S\d{2}E\d{2}') {
        $episode = $matches[0]

        if ($videos[$episode]) {
            Rename-Item $_.FullName -NewName ($videos[$episode].BaseName + ".srt")
        }
    }
}

Change these two lines:

PowerShell
$videoFolder = "D:\TV Shows\24\Season 2"
$subtitleFolder = "D:\TV Shows\24\Season 2\Subtitles"

to your actual folder locations.


What If My Videos Are MP4 Instead of MKV?

Simply replace:

PowerShell
*.mkv

with:

PowerShell
*.mp4

or change:

PowerShell
-Filter *.mkv

to:

PowerShell
-Filter *.mp4

The subtitle files can remain .srt.


Important: Preview First

Bulk-renaming commands can modify dozens of files almost instantly, so I strongly recommend running the preview command first.

Check that:

Plain text
S02E01 -> S02E01
S02E02 -> S02E02
S02E03 -> S02E03

are being matched correctly.

Once the preview looks right, run the actual rename command.


Final Result

Instead of manually renaming an entire season:

Plain text
Video.mkv
Video.srt

PowerShell can do all of it automatically in a few seconds.

The best part is that the video and subtitle releases do not need to have similar filenames.

As long as both contain matching episode identifiers like:

Plain text
S01E01
S01E02
S01E03

the script can pair them and rename the subtitles accordingly.

A small PowerShell command saved me from manually renaming an entire season, and hopefully it saves someone else the same headache.