Here is a commented batch file for this task:
@echo off
rem Setup a local environment for this batch file creating lots
rem of environment variables which should not exist anymore after
rem finishing batch file execution.
setlocal EnableExtensions DisableDelayedExpansion
rem Get all *.mkv and *.srt file names in current directory without path
rem and without file extension loaded into memory assigned to environment
rem variables with name mkv_1, mkv_2, ..., srt_1, srt_2, ... using the
rem two subroutines GetFileList and AddFileToList.
call :GetFileList mkv
call :GetFileList srt
goto ValidateFileCounts
rem Subroutine GetFileList runs command FOR which executes command DIR in
rem a separate command process in background which outputs all file names
rem with the file extension passed to the subroutine as first parameter
rem sorted by name. Each file name output by DIR is assigned to an environment
rem variable with passed file extension, an underscore and an incremented
rem number as variable name. The number of files with given file extension
rem is assigned to an environment variable with name FileCount_Extension.
:GetFileList
set "FileNumber=0"
set "FileExtension=%1"
for /F "delims=" %%I in ('dir *.%FileExtension% /A-D /B /ON 2^>nul') do call :AddFileToList "%%~nI"
set "FileCount_%FileExtension%=%FileNumber%"
goto :EOF
rem Subroutine AddFileToList increments current file number by one and then
rem assigns the file name without file extension and without path passed
rem from calling subroutine GetFileList as first and only parameter to
rem an environment variable with automatically generated varible name.
:AddFileToList
set /A FileNumber+=1
set "%FileExtension%_%FileNumber%=%~1"
goto :EOF
rem After creating the two file lists in memory it is validated that the
rem file rename operation can be started at all. There must be *.srt files
rem found in current directory and the number of *.mkv files must be equal
rem the number of *.srt files.
:ValidateFileCounts
if %FileCount_srt% == 0 (
echo/
echo There are no *.srt files in directory:
echo/
echo %CD%
echo/
pause
goto EndBatch
)
if not %FileCount_mkv% == %FileCount_srt% (
echo/
echo Number of *.mkv files is not equal number of *.srt files in directory:
echo/
echo %CD%
echo/
pause
goto EndBatch
)
rem Now delayed environment variable expansion is needed for the file rename
rem operation in a loop which could not be enabled at beginning of the batch
rem file in case of any file name contains one or more exclamation marks.
rem *.srt files having already the same file name as corresponding *.mkv
rem file detected by identical current and new file name are ignored for
rem the rename operation.
rem It is also not possible to rename a *.srt file to name of a *.srt which
rem already exists. In this case an error message is output for the *.srt
rem file which cannot be renamed and finally PAUSE is executed to give the
rem batch file user the possibility to read all those file rename errors.
rem But it is very unlikely that this error message is displayed ever.
setlocal EnableDelayedExpansion
set "RenameError="
for /L %%I in (1,1,%FileCount_srt%) do (
set "FileNameNew=!mkv_%%I!.srt"
set "FileNameNow=!srt_%%I!.srt"
if not "!FileNameNew!" == "!FileNameNow!" (
if not exist "!FileNameNew!" (
ren "!FileNameNow!" "!FileNameNew!"
) else (
echo Rename file !FileNameNow!
echo to new name !FileNameNew!
echo not possible as such a file exists already.
echo/
set "RenameError=1"
)
)
)
if defined RenameError pause
endlocal
rem The previous environment is restored finally which means all environment
rem variables created by this batch file are removed from memory. There is
rem neither a message output nor batch file processing halted if no error
rem occurred during entire process.
:EndBatch
endlocal
There is no real file name matching algorithm used as it looks like the algorithm is human language intelligence. So the batch file just loads into memory the list of *.mkv file names sorted by name and the list of *.srt file names also sorted by name and then renames first *.srt file to name of first *.mkv file, second *.srt file to name of second *.mkv file, and so on. This simple solution worked for the given examples.
It is possible to insert the command echo
left to command ren
and append command pause
at end of the batch file or run it from within a command prompt window to see all the file rename operations without really doing them for verification by user before really renaming the *.srt files.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
ren /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir
command line with using a separate command process started in background.
Read this answer for details about the commands SETLOCAL and ENDLOCAL and Where does GOTO :EOF return to?