Simon336697
asked on
Help with a batch file and GOTO sections
Hi guys hope you are all well and have a fantastic christmas to all of you.
Guys id love your assistance on this one.
I have a large batch file called master.cmd
========================== ======= master.cmd
call test1.cmd
:DRIVEAREA
:EOF
Now, in the following batch file, called test1.cmd, there is a goto section as follows:
GOTO DRIVEAREA
When I run master.cmd, it correctly calls test1.cmd, but when I get to the GOTO section in test1.cmd to go to section DRIVEAREA, which exists in master.cmd, i get an error, saying cannot find batch label specified.
The reason i am doing this is because master.cmd is huge, so i wanted to break it up into chunks of code, leaving the section labels in the code, and putting in GOTO sections referencing the section names that exist in master.cmd in those other files.
Guys, what am i doing wrong?
Is there a way to reference goto sections in master.cmd from other files?
Any help greatly appreciated.
Guys id love your assistance on this one.
I have a large batch file called master.cmd
==========================
call test1.cmd
:DRIVEAREA
:EOF
Now, in the following batch file, called test1.cmd, there is a goto section as follows:
GOTO DRIVEAREA
When I run master.cmd, it correctly calls test1.cmd, but when I get to the GOTO section in test1.cmd to go to section DRIVEAREA, which exists in master.cmd, i get an error, saying cannot find batch label specified.
The reason i am doing this is because master.cmd is huge, so i wanted to break it up into chunks of code, leaving the section labels in the code, and putting in GOTO sections referencing the section names that exist in master.cmd in those other files.
Guys, what am i doing wrong?
Is there a way to reference goto sections in master.cmd from other files?
Any help greatly appreciated.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Sorry bill, just assume that child.cmd is being called from main.cmd
Without seeing the current large script file it's hard to comment on how best to split it up. One thought I did have though is you may want to consider breaking out the areas that are currently executed via a GOTO, place them in separate BAT files, and then instead of a GOTO do a CALL to them.
In general GOTO is not desired in a BAT file unless there is no other way to work around it.
If you want to share the large script you have now I'd be happy to try and make some specific recommendations.
~bp
In general GOTO is not desired in a BAT file unless there is no other way to work around it.
If you want to share the large script you have now I'd be happy to try and make some specific recommendations.
~bp
ASKER
bill, im not quite sure in what context you mean the calling and called script, and why use the exit command.
If my first script i run is main.cmd, which fires off child.cmd (eg. in main.cmd, there is a line saying:
call child.cmd), is main.cmd the calling script, and child.cmd the "called" script?
If my first script i run is main.cmd, which fires off child.cmd (eg. in main.cmd, there is a line saying:
call child.cmd), is main.cmd the calling script, and child.cmd the "called" script?
Let's try a simple example of what I mean. Attached is a listing of a main.cmd and a child.cmd. At some point in main.cmd we make a call to the child.cmd file. Notice in it we can return to main.cmd using the EXIT statement, and add the /B option to also return an errorlevel to the main.cmd script. Then when control is regained in main.cmd right after the call, we can check the errorlevel returned and take different action depending on the value returned. Does this make any more sense, if not we'll take another swing at it :-).
~bp
~bp
===================== main.cmd
.
.
.
call child.cmd
if errorlevel 1 goto :ErrorsFound
goto :Continue
.
.
.
:Continue
.
.
.
:ErrorsFound
.
.
.
===================== child.cmd
.
.
.
exit /b 1
.
.
.
exit /b 0
ASKER
Bill, you are brilliant, and that is so well explained.
I totally understand it now thanks to you.
Now, with my ridiculously long script, ill tackle it from your angle.
I totally understand it now thanks to you.
Now, with my ridiculously long script, ill tackle it from your angle.
ASKER
Bill can I ask you in your above example,
If in child.cmd, i had the following:
rem zzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz zzzzzzzzzz z
:SCRIPTEVERY1HOUR
rem zzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz zzzzzzzzzz z
set /p LastLine=CONTINUING in 1 HR (%sleep_gtr10_systems% sec) FROM NOW!..<nul
echo.
%fol_tools%\sleep %sleep_gtr10_systems% >nul 2>&1
rem sleep 3600 >nul 2>&1
GOTO PRELIMINARY_FOLDERFILEBUIL DS
rem zzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz zzzzzzzzzz z
:SCRIPTEVERY6HOURS
rem zzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzz zzzzzzzzzz z
set /p LastLine=CONTINUING IN 6 HRS (%sleep_lt10_systems% sec) FROM NOW!..<nul
echo.
%fol_tools%\sleep %sleep_lt10_systems% >nul 2>&1
rem sleep 21600 >nul 2>&1
GOTO PRELIMINARY_FOLDERFILEBUIL DS
Now, because in the above, the PRELIMINARY_FOLDERFILEBUIL DS
is actually a label in main.cmd, and not in child.cmd, this will fail.
So, bill, if i changed the
GOTO PRELIMINARY_FOLDERFILEBUIL DS
to
EXIT /B 1000
and in main.cmd
call child.cmd
if errorlevel 1000 goto :PRELIMINARY_FOLDERFILEBUI LDS
goto :Continue
:PRELIMINARY_FOLDERFILEBUI LDS
should this work, and is this the way you would do it?
If in child.cmd, i had the following:
rem zzzzzzzzzzzzzzzzzzzzzzzzzz
:SCRIPTEVERY1HOUR
rem zzzzzzzzzzzzzzzzzzzzzzzzzz
set /p LastLine=CONTINUING in 1 HR (%sleep_gtr10_systems% sec) FROM NOW!..<nul
echo.
%fol_tools%\sleep %sleep_gtr10_systems% >nul 2>&1
rem sleep 3600 >nul 2>&1
GOTO PRELIMINARY_FOLDERFILEBUIL
rem zzzzzzzzzzzzzzzzzzzzzzzzzz
:SCRIPTEVERY6HOURS
rem zzzzzzzzzzzzzzzzzzzzzzzzzz
set /p LastLine=CONTINUING IN 6 HRS (%sleep_lt10_systems% sec) FROM NOW!..<nul
echo.
%fol_tools%\sleep %sleep_lt10_systems% >nul 2>&1
rem sleep 21600 >nul 2>&1
GOTO PRELIMINARY_FOLDERFILEBUIL
Now, because in the above, the PRELIMINARY_FOLDERFILEBUIL
is actually a label in main.cmd, and not in child.cmd, this will fail.
So, bill, if i changed the
GOTO PRELIMINARY_FOLDERFILEBUIL
to
EXIT /B 1000
and in main.cmd
call child.cmd
if errorlevel 1000 goto :PRELIMINARY_FOLDERFILEBUI
goto :Continue
:PRELIMINARY_FOLDERFILEBUI
should this work, and is this the way you would do it?
Yes, that is the right idea.
Bear in mind that "IF ERRORLEVEL 1000" will be true for all values of ERRORLEVEL greater than or equal to 1000. In your case it might make more sense to use the following variation, which will check for an exact match to the value 1000.
if %errorlevel% == 1000 goto :PRELIMINARY_FOLDERFILEBUI LDS
Can I ask where in main.cmd you will be calling child.cmd from?
~bp
Bear in mind that "IF ERRORLEVEL 1000" will be true for all values of ERRORLEVEL greater than or equal to 1000. In your case it might make more sense to use the following variation, which will check for an exact match to the value 1000.
if %errorlevel% == 1000 goto :PRELIMINARY_FOLDERFILEBUI
Can I ask where in main.cmd you will be calling child.cmd from?
~bp
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
> Qlemo
> As long as you do not use setlocal in any "child" batch file, you can set an environment variable
> for status instead of the somehow tricky errorlevel.
Yes, but then you need 2 statements instead of 1 to return :-).
(I feel obliged to say that since I often get beat up for erroring on the side of being wordy in my batch scripts for readability rather than terse and compact).
> Simon336697
Attached is an example of what Qlemo is mentioning, it's just a slightly different way to get the same result.
~bp
> As long as you do not use setlocal in any "child" batch file, you can set an environment variable
> for status instead of the somehow tricky errorlevel.
Yes, but then you need 2 statements instead of 1 to return :-).
(I feel obliged to say that since I often get beat up for erroring on the side of being wordy in my batch scripts for readability rather than terse and compact).
> Simon336697
Attached is an example of what Qlemo is mentioning, it's just a slightly different way to get the same result.
~bp
===================== main.cmd
.
.
.
call child.cmd
if "%ReturnCode%" == "Errors" goto :ErrorsFound
goto :Continue
.
.
.
:Continue
.
.
.
:ErrorsFound
.
.
.
===================== child.cmd
.
.
.
set ReturnCode=Errors
exit /b
.
.
.
set ReturnCode=Normal
exit /b
ASKER
Hi guys, you are both champions.
Bill, with regards to where in main.cmd I would be calling child.cmd, think of the following *test*.cmd's as all potential candidates for child.cmd
:LOCATION
call %pth_standard%\4b.loop_tes t_1.locati on.cmd
:STATUS
call %pth_standard%\4b.loop_tes t_2.status .cmd
:AVAILABILITY
call %pth_standard%\4b.loop_tes t_3.availa bility.cmd
:IDENTITY
call %pth_standard%\4b.loop_tes t_4.identi ty.cmd
:ACCESSIBILITY
call %pth_standard%\4b.loop_tes t_5.access ibility.cm d
Basically, in main.cmd, main.cmd will take 1 argument, that is a text file of computer names, and loop through each one in that text file, and perform tests against it.
Bill, with regards to where in main.cmd I would be calling child.cmd, think of the following *test*.cmd's as all potential candidates for child.cmd
:LOCATION
call %pth_standard%\4b.loop_tes
:STATUS
call %pth_standard%\4b.loop_tes
:AVAILABILITY
call %pth_standard%\4b.loop_tes
:IDENTITY
call %pth_standard%\4b.loop_tes
:ACCESSIBILITY
call %pth_standard%\4b.loop_tes
Basically, in main.cmd, main.cmd will take 1 argument, that is a text file of computer names, and loop through each one in that text file, and perform tests against it.
Okay, sounds like you have some decent options then, let me know if you run into trouble. Thanks for the points, glad I was able to help.
~bp
~bp
One other option.... which may be appropriate (though I know you have your answer as such) is:
master.cmd:
@echo off
if not "%1"=="" goto %1
child1.cmd
echo After child1.cmd
exit /b
:part2
echo Now in part2
Then in child1.cmd return to the master with:
master.cmd part2
The above just runs:
Now in child1.cmd
Now in part2
Steve
master.cmd:
@echo off
if not "%1"=="" goto %1
child1.cmd
echo After child1.cmd
exit /b
:part2
echo Now in part2
Then in child1.cmd return to the master with:
master.cmd part2
The above just runs:
Now in child1.cmd
Now in part2
Steve
lost the last bit of text there.... was saying along the lines of If you don't use call then the calling batch file stops and changes control to the new batch only. You can then run master.cmd with a command line option of the line label you want it to start again from....
Frankly a combination of these different techniques work in different circumstances.
Steve
Frankly a combination of these different techniques work in different circumstances.
Steve
ASKER
Thanks dragon-it, really appreciate it.
Steve,
Interesting approach. The software engineer in me took a little exception to it at first read, but given the occasional departure of command scripts from a pure programming language here and there that is another useful tool to have.
My initial reaction is that this approach is a bit less like "calling a function" in the way it feels, and I said to myself "oh gosh, I lose all context in the calling (main) script". But the reality of it is the only real context that's typically useful is in environment variables, and as long as none of the script involved use setlocal then we are good.
Actually, does "setlocal enabledelayedexpansion" count as a setlocal, if so that pops up here and there.
Also, I wonder if either approach works better or worse if we try to spawn the child script from within a "block" in the main code, like a FOR of IF code body? I'll have to do some experimenting on that.
Anyway, just rambling a bit, but thanks for the "post points" addition, I always like to hear of different approaches and this one (as you say) can have some good merit depending on the situation and nature of the scripts involved.
Hope the family is well (including the little one) and you have a great holiday.
~bill
Interesting approach. The software engineer in me took a little exception to it at first read, but given the occasional departure of command scripts from a pure programming language here and there that is another useful tool to have.
My initial reaction is that this approach is a bit less like "calling a function" in the way it feels, and I said to myself "oh gosh, I lose all context in the calling (main) script". But the reality of it is the only real context that's typically useful is in environment variables, and as long as none of the script involved use setlocal then we are good.
Actually, does "setlocal enabledelayedexpansion" count as a setlocal, if so that pops up here and there.
Also, I wonder if either approach works better or worse if we try to spawn the child script from within a "block" in the main code, like a FOR of IF code body? I'll have to do some experimenting on that.
Anyway, just rambling a bit, but thanks for the "post points" addition, I always like to hear of different approaches and this one (as you say) can have some good merit depending on the situation and nature of the scripts involved.
Hope the family is well (including the little one) and you have a great holiday.
~bill
Just waiting for a comment from t0t0 about programming style :-)
Heha, I see those bruises are still sensitive...
:-)
:-)
ASKER
Im going to place an example here and hope you can offer advice.
there are 2 scripts below:
main.cmd
and child.cmd
when i kick off main.cmd, i get an error stating that the label :PRELIMINARY_FOLDERFILEBUI
cannot be found in main.cmd from child.cmd
Open in new window