Home > Back-end >  How to run a batch file with a FOR loop with two file names with two parameters?
How to run a batch file with a FOR loop with two file names with two parameters?

Time:07-31

I am using an alass tool to synchronize two subtitles. It is simple to use with one file at a time but I want to use it on multiple files using a loop.

The usage of the tool is like this:

alass.bat correct_subtitle.srt incorrect_subtitle.srt output.srt

I want to do a simple for loop with two parameters with this command:

FOR %i IN (*g.srt) DO FOR %n IN (*t.srt) DO alass.bat %i %n %n

The script is working but I want the command works one time with the second file not looping the first file with all the second files.

I want the script to do like this:

alass.bat example.S01E01.name.ybg.srt Example.S01E01.anotherName.wrt.srt Example.S01E01.anotherName.wrt.srt

FOR %i AND %n IN (*g.srt AND *t.srt) DO alass.bat %i %n %n

All the subtitles are in one folder the correct and incorrect subtitles are like this:

Correct sub (example.S01E01.name.ybg.srt) 

incorrect sub (Example.S01E01.anotherName.wrt.srt)

Correct sub (example.S01E02.name.ybg.srt) 

incorrect sub (Example.S01E02.anotherName.wrt.srt)
    etc.

CodePudding user response:

A simple solution is:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
for %%I in (*g.srt) do (
    set "FileName1=%%I"
    set "FileName2=!FileName1:g.srt=t.srt!"
    call alass.bat "!FileName1!" "!FileName2!" "!FileName2!"
)
endlocal

All occurrences of g.srt in the current first file name are case-insensitive replaced by t.srt to get the second file name by the second SET command line.

This solution works as long as no *.srt file contains one or more exclamation marks in file name.

A little bit slower solution working also for *.srt files with ! in file name as long as alass.bat is good coded is:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%I in (*g.srt) do (
    set "FileName1=%%I"
    setlocal EnableDelayedExpansion
    set "FileName2=!FileName1:g.srt=t.srt!"
    call alass.bat "!FileName1!" "!FileName2!" "!FileName2!"
    endlocal
)
endlocal

The current directory must be the directory containing the *.srt files as well as alass.bat, or the called batch file is in a directory which is included in value of environment variable PATH.

Please note that a batch file must be called from a batch file using the command CALL. The single command line in code works just by chance because of the entire command line is already parsed and in the command queue of the Windows Command Processor cmd.exe processing a batch file. I suggest to read my answer on How to call a batch file that is one level up from the current directory?

It would be also possible to use in the loop:

    call "%~dp0alass.bat" "!FileName1!" "!FileName2!" "!FileName2!"

That results in referencing the other batch file alass.bat with the full path of the batch file containing this command line which means alass.bat must be in same directory as the batch file with the above posted command lines, but the current directory can be any directory.

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 /?
  • echo /?
  • endlocal /?
  • for /?
  • set /?
  • setlocal /?

CodePudding user response:

NOTE: This answer relates to Revision 9 of the question.

I would do it with the following :

@echo off
setlocal EnableExtensions DisableDelayedexpansion

rem // Define constants here:
set "_ROOT=%~dp0."    & rem // (target directory)
set "_SUFF1=g"        & rem // (suffix for base names of 1st files)
set "_SUFF2=T"        & rem // (suffix for base names of 2nd files)
set "_MASK=*%_SUFF1%" & rem // (name search pattern for 1st files)
set "_EXT=.srt"       & rem // (extensions for 1st and 2nd files)

rem // Change into target directory:
pushd "%_ROOT%" && (
    rem // Loop over 1st files:
    for %%I in ("%_MASK%%_EXT%") do (
        rem // Store base name of currently iterated 1st file:
        set "NAME=%%~nI"
        setlocal EnableDelayedExpansion
        rem /* Build base name of respective 2nd file; temporarily appending `|` to the
        rem    name (which cannot occur in a file name) ensures to just replace the very
        rem    last occurrence of the suffix: */
        set "REPL=!NAME!|" & set "REPL=!REPL:%_SUFF1%|=%_SUFF2%!"
        rem // Skip in case there is no respective 2nd file:
        if exist "!REPL!!_EXT!" (
            rem /* Call sub-script with 1st and 2nd file as input files and 2nd one also
            rem    as output file, preventing delayed expansion but utilising the second
            rem    `%`-expansion phase established by `call` in order to avoid doubling
            rem    of `^`-symbols as well as loss of `%`-signs: */
            REM call alass.bat "!NAME!!_EXT!" "!REPL!!_EXT!" "!REPL!!_EXT!"
            call alass.bat "%%NAME%%%%_EXT%%" "%%REPL%%%%_EXT%%" "%%REPL%%%%_EXT%%"
            rem /* Erase 2nd file to prevent reprocessing of same file pairs in case of
            rem    re-execution of the script: */
            ECHO del "!NAME!!_EXT!"
        )
        endlocal
    )
    rem // Return from target directory:
    popd
)

endlocal
exit /B

This approach correctly handles file names with characters !, ^ and %. You can prove that when you create an interim sub-script alass.bat with the following contents:

@echo off
setlocal DisableDelayedExpansion
echo(%0 %*
endlocal
exit /B

If you used the commented-out call command line (with the upper-case REM in front), ^-symbols would become doubled and %-signs would become lost.

In case the tool alass.bat overwrites the original *T.srt files, which is what I assume, the script deletes the *g.srt files (when removing the upper-case ECHO in front of the related command) in order not to reprocess the same pair of files upon re-execution of the script.

  • Related