Search code examples
methodsbatch-filecmdinternal

Windows batch scripting internal functions passing variables


OK so im trying to do batch video processing and i'd like to get it condensed down to a single batch file rather than 5 but im not able to pass variables to internal functions the same as i would pass them to an external .bat file.

heres my "all in one" version

mkdir new

mkdir new\fonts

forfiles /M *.mkv /C "cmd /c call :mkvextract @file @fname" >> log.txt 2>&1

forfiles /M *.mkv /C "cmd /c call :mkvmerge @file" >> merge.txt 2>&1

forfiles /M *.mkv /C "cmd /c call :makeavs @file @fname" >> log.txt 2>&1

forfiles /M *.mkv /C "cmd /c call :getfonts @file @fname" >> fonts.txt 2>&1

forfiles /M *.ttf /C "cmd /c call :movefonts @file" >> fonts.txt 2>&1

forfiles /M *.TTF /C "cmd /c call :movefonts @file" >> fonts.txt 2>&1

forfiles /M *.otf /C "cmd /c call :movefonts @file" >> fonts.txt 2>&1

forfiles /M *.OTF /C "cmd /c call :movefonts @file" >> fonts.txt 2>&1

:mkvextract

"C:\Program Files (x86)\MKVToolNix\mkvextract.exe" --ui-language en tracks "%~1" 2:"%CD%\new\%~2_track3_eng.ass"

goto :EOF

:mkvmerge

set mkvorig=%CD%\%~1
set mkvorig=%mkvorig:\=\\%

set mkvnew=%CD%\new\%~1
set mkvnew=%mkvnew:\=\\%

"C:\Program Files (x86)\MKVToolNix\mkvmerge.exe" -o "%mkvnew%"  "--language" "0:jpn" "--default-track" "0:yes" "--forced-track" "0:no" "--display-dimensions" "0:1920x1080" "--language" "1:jpn" "--default-track" "1:yes" "--forced-track" "1:no" "-a" "1" "-d" "0" "--no-attachments" "-S" "-T" "--no-global-tags" "--no-chapters" "(" "%mkvorig%" ")" "--track-order" "0:0,0:1"

goto :EOF

:makeavs

echo Directshowsource("new\%~1") >"new\%~2.avs"
echo textsub("new\%~2_track3_eng.ass") >>"new\%~2.avs"

goto :EOF

:getfonts

"C:\Program Files (x86)\MKVToolNix\mkvextract.exe" attachments "%~1" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

goto :EOF


:movefonts

move %~1 new\fonts

goto :EOF

The "five .bat files" version is as follows:

mkdir new

mkdir new\fonts

forfiles /M *.mkv /C "cmd /c mkvextract.bat @file @fname" >> log.txt 2>&1

forfiles /M *.mkv /C "cmd /c mkvmerge.bat @file" >> merge.txt 2>&1

forfiles /M *.mkv /C "cmd /c makeavs.bat @file @fname" >> log.txt 2>&1

forfiles /M *.mkv /C "cmd /c getfonts.bat @file @fname" >> fonts.txt 2>&1

forfiles /M *.ttf /C "cmd /c movefonts.bat @file" >> fonts.txt 2>&1

forfiles /M *.TTF /C "cmd /c movefonts.bat @file" >> fonts.txt 2>&1

forfiles /M *.otf /C "cmd /c movefonts.bat @file" >> fonts.txt 2>&1

forfiles /M *.OTF /C "cmd /c movefonts.bat @file" >> fonts.txt 2>&1

im not quite sure how if im doing function calls correctly either but it looks right base don what i found here: http://batcheero.blogspot.com/2007/07/function-call-in-batch.html


Solution

  • The command(s) executed by forfiles are within a brand new CMD.EXE session. They are no longer in your master batch context, so you cannot call a subroutine within your master batch script.

    You could restructure your master script to call itself and and pass the name of the routine as an argument. If the label exists your script can then GOTO that label.

    Your first script was also missing EXIT /B or GOTO :EOF before the first subroutine.

    You do not need to make intermediate directories. You can directly make new\fonts and new will be created if it does not yet exist.

    @echo off
    
    :: If first argument is a valid label then GOTO that label
    if "%~1" neq "" findstr /bc:":%~1" "%~f0" >nul && (
      shift /1
      goto %~1
    )
    
    ::Main program
    if not exist new\fonts mkdir new\fonts
    forfiles /M *.mkv /C "cmd /c "%~f0" mkvextract @file @fname" >> log.txt 2>&1
    forfiles /M *.mkv /C "cmd /c "%~f0" mkvmerge @file" >> merge.txt 2>&1
    forfiles /M *.mkv /C "cmd /c "%~f0" makeavs @file @fname" >> log.txt 2>&1
    forfiles /M *.mkv /C "cmd /c "%~f0" getfonts @file @fname" >> fonts.txt 2>&1
    forfiles /M *.ttf /C "cmd /c "%~f0" movefonts @file" >> fonts.txt 2>&1
    forfiles /M *.TTF /C "cmd /c "%~f0" movefonts @file" >> fonts.txt 2>&1
    forfiles /M *.otf /C "cmd /c "%~f0" movefonts @file" >> fonts.txt 2>&1
    forfiles /M *.OTF /C "cmd /c "%~f0" movefonts @file" >> fonts.txt 2>&1
    exit /b
    
    :mkvextract
    "C:\Program Files (x86)\MKVToolNix\mkvextract.exe" --ui-language en tracks "%~1" 2:"%CD%\new\%~2_track3_eng.ass"
    exit /b
    
    :mkvmerge
    set mkvorig=%CD%\%~1
    set mkvorig=%mkvorig:\=\\%
    set mkvnew=%CD%\new\%~1
    set mkvnew=%mkvnew:\=\\%
    "C:\Program Files (x86)\MKVToolNix\mkvmerge.exe" -o "%mkvnew%"  "--language" "0:jpn" "--default-track" "0:yes" "--forced-track" "0:no" "--display-dimensions" "0:1920x1080" "--language" "1:jpn" "--default-track" "1:yes" "--forced-track" "1:no" "-a" "1" "-d" "0" "--no-attachments" "-S" "-T" "--no-global-tags" "--no-chapters" "(" "%mkvorig%" ")" "--track-order" "0:0,0:1"
    exit /b
    
    :makeavs
    echo Directshowsource("new\%~1") >"new\%~2.avs"
    echo textsub("new\%~2_track3_eng.ass") >>"new\%~2.avs"
    exit /b
    
    :getfonts
    "C:\Program Files (x86)\MKVToolNix\mkvextract.exe" attachments "%~1" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    exit /b
    
    :movefonts
    move %~1 new\fonts
    exit /b