Page 1 of 1

Functions In Batch

Posted: 24 Jun 2011 07:01
by nitt
What is the closest thing to a function in Batch?

I've been playing around trying to think of something but the best I could get was making a function.bat file with the super basic code

Code: Select all

:%1
(
echo %2 %3 %4 %5 %6 %7 %8 %9
)>%1.bat


That just allows you to like use

Code: Select all

call function greet echo hi
call greet
pause


So basically it just creates a Batch file with your code so you can then call on it later.

I'm looking for a more complicated one, though.

Re: Functions In Batch

Posted: 24 Jun 2011 07:24
by orange_batch
Well, that macro stuff seems closest as far as the execution goes in other languages, but traditionally in batch, it's calling either a separate batch file, or a label (my preference). But it seems you mean, dynamically creating a function? Not sure I understand the purpose, but it looks like you're on the right track. Though, utilizing the shift command many more arguments could be used, but I think writing it in one argument would be better due to all the bad spaces.

Did you know that batch files are self-modifiable? Though I think if you add code -before- the current position, it will screw up. So if for some reason you want a batch file to dynamically create a function onto itself rather than a new file, I think...

Code: Select all

@echo off

call :addNewFunction %0 greet "echo:Hello World.&echo:echo:What's up?"

call :greet

pause
exit

:addNewFunction
(
echo:
echo::%2
echo:%~3
echo:exit/b
)>>%1
exit/b

Notice that:
1. We have to pass the path of the current file to the label call, because the arguments change during a call and we need that to append to the current file.
2. Note that only the first echo is provided for the actual commands, as the bare necessity.
3. Beware that every time you run the file, it'll recreate those functions lol. A fix could be put in place.
4. Reproducing special characters like % and & require escaping them, as they will be interpreted by Command Prompt during the function's creation.

EDIT: Fixed #3. Adds a simple label and "defined" argument clause.

Code: Select all

@echo off

call :addNewFunction %0 greet "echo:Hello World.&echo:echo:What's up?"

call :greet

pause
exit

:addNewFunction
call :%2 func_defined 2>nul&&exit/b
(
echo:
echo::%2
echo:if "%%~1"=="func_defined" exit/b
echo:%~3
echo:exit/b
)>>%1
exit/b

Re: Functions In Batch

Posted: 24 Jun 2011 16:05
by Acy Forsythe
I messed around with this a long time ago when Choice was first introduced, but I couldn't come up with a viable reason to create extra conditional code during run-time when I could just create the conditional code at design-time.

I've been trying to think of a use, and the only thing I have ever been able to come up with is a recursive batch file that calls itself repeatedly changing the actually commands that it runs through with each recursive loop until it accomplishes it's goal.

I am absolutely positive that if we come up with an application for that it would be brilliant but fairly useless...

The closest thing I have found useful, is the ability for a batch file to parse it's own text. I'm actually working on a setup.bat creator that will take several batch files and directory paths, and create a single setup.bat file that parses itself and re-creates the individual batch files in the specified directories. And I only have a single usefull application for that so it's a one-shot deal and I can even think of several better ways of doing it, this was just more fun.

Re: Functions In Batch

Posted: 24 Jun 2011 16:58
by Acy Forsythe
Here's an example of a recursive batch file, but it doesn't change itself, it could though...

Little_Indian.bat

Code: Select all

@echo off
SETLOCAL
if not defined Counter Set /A Counter=1 ELSE Set /A Counter=%1
Set /A Divis=%Counter% / 3
Set /A Divis=%Divis% * 3

For /F "tokens=1-2 delims=_" %%a in ("%~0") DO (
IF %Counter%==%Divis% (Echo %Counter% %%a %%bs &Echo....) ELSE (IF %Counter%==10 (Echo %Counter% %%a %%b Boys &Echo. ) ELSE Echo %Counter% %%a)
SET /a Counter=%Counter% +1)
IF NOT %Counter%==11 %0 %Counter%

pause
endlocal
exit /b


I know it's silly but I was trying to come up with a quick example and counting is a quick example :)

EDIT: Fixed a quick bug... I don't know why I'm getting "Missing Operator"