简体   繁体   中英

How can I call a function that is defined in another batch file, in my current batch?

I know that I can call another batch file using call path_to_other_batch_file.bat .

However, I don't know how can I call functions inside that file.

I have this batch file called Message.bat :

@echo off

EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

And I want to use these functions in my other batch files so that I can simply write call:Error something went wrong without worrying about colors all the time.

I use it this way in Other.bat , but it does not work:

call C:\Infra\Message.bat
call:Error something went wrong

I receive this error:

The system cannot find the batch label specified - Error

So, how can I call those methods defined in my Message.bat file?

In your main batch(es)

call message error something went wrong

In message

@echo off
goto %1

:error
for /f "tokens=1*" %%L in ("%*") do echo %%M
exit /b 0

really not that hard...

or, better in message.bat

@echo off
FOR /f "tokens=1*" %%L IN ("%*") DO CALL :%%L %%M
EXIT /B %ERRORLEVEL%

:Error
echo [31m %* [0m
EXIT /B 0

:Warning

...

There are (at least) the two possibilities, one of which is courtesy of user jeb in this answer of him – so please give adequate credit to him by up-voting his post!

main.bat , establishing two calls of label :Label in sub.bat :

@echo off
echo/
echo ^>^>^> Supply `:Label` as the first argument:
call "%~dp0sub.bat" :Label arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
echo/
echo ^>^>^> Embed `:Label` within the script path:
call "%~d0\:Label:\..%~p0sub.bat" arg1 arg2 arg3
echo ^>^>^> Returned to main script at this point.
exit /B

sub.bat , resolving label :Label in two distinct ways:

@echo off
echo Original path: "%~0"
echo Resolved path: "%~f0"
echo 1st argument : "%~1"
echo All arguments: %*
rem // Check whether first argument begins with (a) colon(s):
for /F "tokens=* delims=:" %%L in ("%~1") do if not "%%~L"=="%~1" goto :%%~L
rem // Check whether script path contains something between colons behind the drive:
for /F "tokens=3 delims=:" %%L in ("%~0") do goto :%%~L
rem // This code in the main section is never reached when a label has been provided.
exit /B

:Label
echo Function call: "%~f0" %*
exit /B

And this is the console output upon running main.bat :

 >>> Supply `:Label` as the first argument: Original path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" Resolved path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" 1st argument : ":Label" All arguments: :Label arg1 arg2 arg3 Function call: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" :Label arg1 arg2 arg3 >>> Returned to main script at this point. >>> Embed `:Label` within the script path: Original path: "C:\:Label:\..\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" Resolved path: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" 1st argument : "arg1" All arguments: arg1 arg2 arg3 Function call: "C:\LocalFiles\TiKi-ASIC\doc\work\TiCi-SV\Spec\sub.bat" arg1 arg2 arg3 >>> Returned to main script at this point.

As you may have noticed, in the first call, the label :Label is also part of the argument string %* which you have to pay specific attention to, though in the second call (applying said jeb 's method), %* contains the pure argument string without an extra item.

There's no built-in way to do that. call will either call an external file, an internal command or a label in the current file .

But, if you can change message.bat , you can make it take an additional argument, and call it. Then call will search in its own labels.

You'll have to take extra care to not pass the first argument to the label. For that, you can use the code from this answer :

@echo off

set "fn=%1"
shift

::"exit /b" is the same as "exit /b %errorlevel%"
if "%fn%"=="" exit /b

set "line=%1"
:loop
shift
if not "%1"=="" (
  set "line=%line% %1"
  goto :loop
)
call :%fn% %line%
exit /b

:Error
echo [31m %* [0m
EXIT /B 0

:Warning
echo [33m %* [0m
EXIT /B 0

:Info
echo [34m %* [0m
EXIT /B 0

:Success
echo [32m %* [0m
EXIT /B 0

:Reset
echo [37m %* [0m
EXIT /B 0

Then, you can call it like:

call message.bat error Something went wrong

Labels can sometimes become cluttered if you have multiple options. It is good for multiple tasks if some meets the criteria, but you seem to only want to change colors on events. So I will simply say do not use labels at all. The content of message.bat add:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1
set "line=%*"
set "label=%1"
call set "rest=%%line:%label% =%%"

if /i "%1" == "Error" set "severity=[31m%rest%"
if /i "%1" == "Warning" set "severity=[33m%rest%"
if /i "%1" == "Info" set "severity=[34m%rest%"
if /i "%1" == "Success" set "severity=[32m%rest%"
if /i "%1" == "Reset" set "severity=[37m%rest%"

echo %e%%severity%%e%[0m
exit /b 0

To call this from another batch, simply do:

call messages.bat warning something went wrong

There is an odd chance that you want to add the actual severities into the message as well, and not just change the text color, then simply narrow it down to:

@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "e=%%a"
if "%1" == "" exit /b 1

if /i "%1" == "Error" set "severity=[31m%*"
if /i "%1" == "Warning" set "severity=[33m%*"
if /i "%1" == "Info" set "severity=[34m%*"
if /i "%1" == "Success" set "severity=[32m%*"
if /i "%1" == "Reset" set "severity=[37m%*"

echo %e%%severity%%e%[0m
exit /b 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM