31

I looking for a way using windows batch file that call sub-batch file which pass 1-9 parameters and return value (string) without the need of saving the return value into file/etc. The return value I save into variable like did in @FOR /F

I look at

@FOR /F "tokens=*" %%i IN ('%find_OS_version%') DO SET OS_VER=%%i

and

Call function/batch %arg1% %arg2%

I'm not seeing how I can setup to do this

EDIT: dbenham somewhat answer my question. His example was between batch file main part and function. My question was between two different batch files. Base off dbenham answer this is the follow layout.

Main batch file

CALL sub_batch_file.bat  return_here "Second parameter input"

REM echo is Second parameter input
ECHO %return_here%
REM End of main-batch file

sub_batch_file.bat

@ECHO OFF
SETLOCAL

REM ~ removes the " "
SET input=%~2
(
    ENDLOCAL
    SET %1=%input%
)
exit /b
REM End of sub-batch file
TheMadCat
  • 313
  • 1
  • 3
  • 6
  • 1
    How does the sub-batch return its value? On the screen? Or is it where you're stuck? – Eitan T Jul 14 '12 at 09:05
  • Right now I have the return variable echo because the "@FOR /F" catches the echo and save into variable. So in short I want the return save into variable while the same time be able to pass between 1 to 9 parameters. – TheMadCat Jul 14 '12 at 18:01

3 Answers3

53

Generally batch functions return values in one of two ways:

1) A single integer value can be returned via the errorlevel by using EXIT /B n where n = some number.

@echo off
setlocal
call :sum 1 2
echo the answer is %errorlevel%
exit /b

:sum
setlocal
set /a "rtn=%1 + %2"
exit /b %rtn%

2) The more flexible method is to use environment variables to return one or more values

@echo off
setlocal
call :test 1 2
echo The sum %sum% is %type%
call :test 1 3
echo The sum %sum% is %type%
exit /b

:test
set /a "sum=%1 + %2, type=sum %% 2"
if %type%==0 (set "type=even") else (set "type=odd")
exit /b

The name of the variable where the answer is to be stored can be passed in as a parameter! And the intermediate values can be hidden from the main program.

@echo off
setlocal
call :test 1 2 sum1 type1
call :test 1 3 sum2 type2
echo 1st sum %sum1% is %type1%
echo 2nd sum %sum2% is %type2%
exit /b

:test
setlocal
set /a "sum=%1 + %2, type=sum %% 2"
if %type%==0 (set "type=even") else (set "type=odd")
( endlocal
  set "%3=%sum%"
  set "%4=%type%"
)
exit /b

For a complete explanation of how the last example works, read this excellent batch function tutorial at DOStips.

Update

The above still has limits as to the content that can be returned. See https://stackoverflow.com/a/8254331/1012053 for an alternative method based on FOR that supports a wider range of values. And see https://stackoverflow.com/a/8257951/1012053 for a "magical" technique that can safely return absolutely any value with length < ~8190, under any circumstance.

Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
5

Small TIP

Setlocal EnableDelayedExpansion
IF 1==1 (
    CALL :LABEL
    echo 1: %errorlevel%
    echo 2: !errorlevel!
)
echo 3: %errorlevel%

:LABEL
EXIT /B 5

Output will be:

1: 0
2: 5
3: 5

EnableDelayedExpansion allows you to use !var_name! to expand var at execution time, rather then parse time.

befzz
  • 1,232
  • 13
  • 11
1

You're missing a couple things:

  • Use backticks not single quotes.
  • add usebackq inside the double quotes with the tokens command.

This character ` not this character '

On an american english keyboard, the backtick is shift-tilde, which is usually to the left of the 1 in the number row.

@FOR /F "usebackq tokens=*" %%i IN (`%find_OS_version%`) DO SET OS_VER=%%i
JimR
  • 15,513
  • 2
  • 20
  • 26
  • 3
    Single-quotes (apostrophes) are ok too, if there aren't any in `find_OS_version`. There's no special need to use backquotes and `usebackq`. Also, this answer doesn't solve the OP's problem. – Eitan T Jul 14 '12 at 09:01
  • 2
    Location of the grave accent is also wrong; tilde needs shift, grave not. – Joey Jul 14 '12 at 09:04
  • I see, how do I pass parameters to sub-batch file using @FOR /F "usebackq tokens=*" ? – TheMadCat Jul 14 '12 at 18:03
  • The only time USEBACKQ is required is when reading a file whose name contains spaces. I'm not aware of any case where USEBACKQ is needed when executing a command. – dbenham Oct 07 '14 at 12:10
  • @EitanT - The command itself may contain as many `'` as are needed, as long as the command is enclosed in `'` at either end. There is no need to escape or worry about internal `'`. The same is true regarding the backtick when using USEBACKQ. – dbenham Oct 07 '14 at 12:17