Windows 95/98/ME users often find it convenient to embed
small non-batch scripts within a Batch file. This ShellRedirect
technique allows relatively compact embedding of many
types of script. Each script is placed in a separate Subroutine
called in a child shell (with %COMSPEC%/c ) and the calling
line is redirected to the workfile that is to hold the extracted script.
Each line of text to be redirected to the workfile is prefixed with
%3 which will contain ECHO. when the Subroutine is called. Any
special characters such as < | and > are generated by a custom
prompt with an ECHO ON+@PROMPT+% blank line %+@ECHO OFF
combo. This is captured by the same redirection that receives
the ECHOed lines. Since the Subroutine is called in a child
shell, there is no need to save/restore the current PROMPT.
Changes to the PROMPT in a child shell have scope _only_
in that shell (and its children).
This technique is sometimes more useful than the usual way
of extracting the script with FIND filtering on the Batch file itself,
(and saves a Subroutine call to find the path to current Batch file).
This simple outline shows the basic syntax:
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
:: Script embedding demo
%COMSPEC%/c %0 GOTO: _SCRIPT ECHO.>{TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
GOTO EOF (=Subroutine code follows=)
:_SCRIPT (Usage: %COMSPEC%/c %0 GOTO: _SCRIPT ECHO.>CaptureFile)
%3This line is ECHOed and redirected to CaptureFile
%3So is this line
ECHO ON
@PROMPT This line has $L ("<") $G (">") and $B ("|") symbols
% This ECHOs custom PROMPT for redirection to CaptureFile %
@ECHO OFF
%3And this line is simply ECHOed and redirected to CaptureFile
:EOF (End-of-file)
====End cut-and-paste (omit this line)
Cut-and-paste text between the ==== lines into file with extension .BAT
(and suitable base name). Lines that don't begin with two spaces have
wrapped accidentally. The code sample is purely for demonstration and
study purposes. It was written/tested in the Win9x GUI.
============Screen capture Windows 95
C:\WORK>script.bat
This line is ECHOed and redirected to CaptureFile
So is this line
This line has < ("<") > (">") and | ("|") symbols
And this line is simply ECHOed and redirected to CaptureFile
C:\WORK>
============End screen capture
Note that the PROMPT technique produces one normal blank line
(carriage return + linefeed combo) immediately preceding the
required text. This method is suitable for generating VBS
scripts, HTML files, and Debug scripts.
This demo shows it used to create and run Debug scripts to place
two-digit calendar tokens for current Century Year Month and Day
read from CMOS RAM. Notice that this technique makes it
easy to comment the Debug scripts with % Comments %
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
%COMSPEC%/c %0 GOTO: _SCRIP1 ECHO.|debug|find "0010">{TEMP}.BAT
%COMSPEC%/c %0 GOTO: _SCRIP2 ECHO.|debug {TEMP}.BAT>NUL
CALL {TEMP}.BAT %0 _DATE1A
DEL {TEMP}.BAT
ECHO. Century/Year/Month/DAY CC=%CC% YY=%YY% MO=%MO% DD=%DD%
FOR %%V IN (CC YY MO DD) DO SET %%V=
GOTO EOF (=Subroutine code follows=)
:_SCRIP1 (Usage: %COMSPEC%/c %0 GOTO: _SCRIP1 ECHO.)
%3a100 % Enter Assembly mode of Debug %
%3mov ah,04 % Select ah=subfunction 4 (read date) %
%3int 1a % of INT 1A %
%3mov [0012],cx % Move Century+Year tokens to memory at 12,13 %
%3mov [0014],dx % Move Month+Day tokens to memory at 14,15 %
%3ret % Invoke the INT 20 at offset 00 of Debug %
%3 % Blank line to exit Debug assembly mode %
%3g % Execute the above code %
%3d12 15 % Dump results from memory locations 12-15 %
%3q % Quit Debug session %
GOTO EOF (=Subroutine code follows=)
:_SCRIP2 (Usage: %COMSPEC%/c %0 GOTO: _SCRIP2 ECHO.)
%3e100'CALL %%1 GOTO: %%2' % Enter Recall code into the workfile %
%3w % Write edited file back to itself %
%3q % Quit Debug session %
GOTO EOF (=Subroutine code follows=)
:_DATE1A (Usage: CALL %0 GOTO: _DATE1A)
FOR %%V IN ("CC=%4" "YY=%3" "MO=%6" "DD=%5") DO SET %%V
:EOF (End-of-file)
====End cut-and-paste (omit this line)
Cut-and-paste text between the ==== lines into file with extension .BAT
(and suitable base name). Lines that don't begin with two spaces have
wrapped accidentally. The code sample is purely for demonstration and
study purposes. It was written/tested in the Win9x GUI.
============Screen capture Windows 95
C:\WORK>demo
Century/Year/Month/DAY CC=20 YY=02 MO=03 DD=24
C:\WORK>
============End screen capture
--
(pp) William Allen
Note:
===Batch Subroutines
A Batch subroutine is a chunk of Batch code, isolated from
the rest of the script by a GOTO EOF instruction. This "jumps"
over it, so it doesn't runs unless specifically invoked.
The initial Subroutine handler line:
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
is transparent to normal Batch parameters, but intercepts all
Subroutine calls by checking for Subroutine flag GOTO: in %1
and uses Subroutine ID in %2 to execute appropriate Subroutine.
To MIX any of our Batch subroutines with your own code, simply
ensure your own code begins with our two standard lines:
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
and ends with our standard End-of-file label line:
:EOF (End-of-file)
Include the code for the Subroutine (usually better in a section at/near
the end of your script). Subroutine code is introduced by the lines:
GOTO EOF (=Subroutine code follows=)
:_SRNAME (Usage: CALL %0 GOTO: _SRNAME parameters)
where _SRNAME is the Subroutine ID (the Usage instructions will
normally include the CALLing protocol).
There can be many such Subroutines in any particular Batch script;
they remain independent of each other when properly written.
For those interested, the operation of this particular Debug
script is explained in detail in one of our previous posts:
Naming files or folders with current date and time
http://groups.google.com/groups?selm=a5nraf$8pued$1...@ID-55970.news.dfncis.de
Date: Fri, 1 Mar 2002
--
(pp) William Allen
Hmm, why prefix all lines of text to be redirected with %3 since %3
must contain always ECHO. when the subroutine is called? Why not
"hardcode" the ECHO.?
--
Frank-Peter Schultze <fpsch...@bigfoot.de>, http://www.fpschultze.de/
Hi,
The other methods that we found is sometimes
better and other times not better.
@ECHO OFF
GOTO Batch
The 1'th captured !
The 2'th captured !
The 3'th captured !
The 4'th captured !
:Batch
IF NOT EXIST %0 %0.BAT
find " % %!" < %0 > {TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
GOTO EOF ------------------------------
@ECHO OFF > {TEMP}
ECHO The 1'th captured >> {TEMP}
ECHO The 2'th captured >> {TEMP}
ECHO The 3'th captured >> {TEMP}
ECHO EXIT|%COMSPEC%/kPROMPT The 4'th captured$_|find " ">>{TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
@GOTO EOF ------------------------------
@ECHO OFF
IF (GOTO:)==(%1) %1%2
%COMSPEC%/c%0 GOTO: _SCRIPT ECHO.>{TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
GOTO EOF
:_SCRIPT
%3: The 1'th captured
%3: The 2'th captured_
ECHO ON
@PROMPT : The 3'th captured
% %
@ECHO OFF
%3: The 4'th captured
GOTO EOF -------------------------------
With ECHO ON in the _SCRIPT section,
@IF (GOTO:)==(%1) %1%2
@ECHO OFF
%COMSPEC%/c%0 GOTO: _SCRIPT ECHO.>{TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
GOTO EOF
:_SCRIPT
@%3: The 1'th captured
@%3: The 2'th captured
@PROMPT : The 4'th captured
@%3: The 3'th captured_
@GOTO EOF ------------------------------
This one is interesting:
@ECHO OFF
IF (GOTO:)==(%1) %1%2
%COMSPEC%/c%0 GOTO: _SCRIPT ECHO.>{TEMP}
FOR %%C IN (TYPE DEL) DO %%C {TEMP}
GOTO EOF
:_SCRIPT
%3: The 3'th captured
%3: The 4'th captured
PROMPT : The 1'th captured
FOR %%c in (NUL CON) do CTTY %%c
ECHO ON
% %
@ECHO OFF
%3: The 2'th captured
GOTO EOF -------------------------------
Benny Pedersen,
:EOF
1) Soft coding the ECHO. action is more compact.
2) Soft coding is usually more adaptable, and suggestive of
new ideas, which may be productive in some situations.
The general point is to use an approach that tends to stimulate
further ideas. For example, taking the DATE demo, by using
soft-coding you can combine both Debug scripts in one, turning
some lines off and on in different Subroutine calls. And also make
use of any common lines in several calls. In some cases, different
embedded scripts may have many lines in common, with only
small sections that actually differ.
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF (GOTO:)==(%1) %1%2 (Subroutine handler)
%COMSPEC%/c %0 GOTO: _SCRIPT ECHO. REM: ECHO.|debug|find "0010">{TEMP}.BAT
%COMSPEC%/c %0 GOTO: _SCRIPT REM: ECHO. ECHO.|debug {TEMP}.BAT>NUL
CALL {TEMP}.BAT %0 _DATE1A
DEL {TEMP}.BAT
ECHO. Century/Year/Month/DAY CC=%CC% YY=%YY% MO=%MO% DD=%DD%
FOR %%V IN (CC YY MO DD) DO SET %%V=
GOTO EOF (=Subroutine code follows=)
:_SCRIPT (Usage: %COMSPEC%/c %0 GOTO: _SCRIPT REM:/ECHO. ECHO./REM: ECHO.)
%3a100 % Enter Assembly mode of Debug %
%3mov ah,04 % Select ah=subfunction 4 (read date) %
%3int 1a % of INT 1A %
%3mov [0012],cx % Move Century+Year tokens to memory at 12,13 %
%3mov [0014],dx % Move Month+Day tokens to memory at 14,15 %
%3ret % Invoke the INT 20 at offset 00 of Debug %
%3 % Blank line to exit Debug assembly mode %
%3g % Execute the above code %
%3d12 15 % Dump results from memory locations 12-15 %
%4e100'CALL %%1 GOTO: %%2' % Enter Recall code into the workfile %
%4w % Write edited file back to itself %
%5q % Quit Debug session - common line %
GOTO EOF (=Subroutine code follows=)
:_DATE1A (Usage: CALL %0 GOTO: _DATE1A)
FOR %%V IN ("CC=%4" "YY=%3" "MO=%6" "DD=%5") DO SET %%V
:EOF (End-of-file)
====End cut-and-paste (omit this line)
Cut-and-paste text between the ==== lines into file with extension .BAT
(and suitable base name). Lines that don't begin with two spaces have
wrapped accidentally. The code sample is purely for demonstration and
study purposes. It was written/tested in the Win9x GUI.
--
(pp) William Allen
When %0 is used without a CALL or %COMSPEC%, then
it won't return. That can be used to avoid a GOTO:EOF.
But if %0 is restarted at once, then why not put parameters
along with it so the next lines would be more brief.
@ECHO OFF
%2 %0 ECHO :: parameter (Run once, won't return).
%COMSPEC%/c%0 %1 GOTO:_SCRIPT 7 |debug|find/v "-"
%COMSPEC%/c%0 %1 GOTO:_SCRIPT 8 |debug|find/v "-"
%COMSPEC%/c%0 %1 GOTO:_SCRIPT 9 |debug|find/v "-"
%COMSPEC%/c%0 %1 GOTO:_SCRIPT 32|debug|find/v "-"
ECHO. debug got this:
:_SCRIPT
%1 o70,%3
%1 i71
%1 q
@ECHO OFF
%1
%COMSPEC%/c%0 GOTO:OUTPUT|debug|find/v "-">%temp%.\$.BAT
%COMSPEC%/c%0 GOTO:PREFIX
FOR %%c in (CALL DEL GOTO:EOF) do %%c %temp%.\$.BAT
:OUTPUT
PROMPT o70,7$_i71$_o70,8$_i71$_o70,9$_i71$_o70,32$_i71$_q
FOR %%c in (ECHO GOTO:EOF) do %%c ON
:PREFIX
:: ECHO @ECHO OFF>>%temp%.\$.BAT
PROMPT CALL %0 GOTO:RESULT =
CTTY NUL
%COMSPEC%/c%temp%.\$.BAT|find "=">%temp%.\$.BAT
:RESULT
ECHO. %2
:: SET D=%D% %2
:EOF