Frequently Asked Questions about Batch
(not an official FAQ, just answering frequently asked questions...)

How do I write a batch? 
Where can I get batch information? 
How do I perform if-then-else in batch? 
How do I use the [insert name] command? 
How do I get deltree to work without giving permission? 
How do I delete all files in a dir without giving permission? 
How do I check if a directory exists? 
How do I set a variable to the contents of a file? 
How do I set a variable to the output of a program? 
How do I extract a line from a file and set a variable to it? 
How do I get keystrokes from the user or make a menu? 
How do I get string input from the user? 
How do I concatenate files into one file? 
How do I start Windows 95 programs or associated files? 
How do I save and restore the current directory? 
How do I check the output of a program for a specific string? 
How do I rename a file to the current time or date? 
How do I send keystrokes to a program? 
What do all those }{ and $ things mean? 
Utility programs for batch files 

The following is optimised for Dos 6 and Windows 95.
Not responsible for wrong answers, but I gladly try to
answer batch questions. So do many others, just ask us.
No "how do I destroy" type questions please.

Many basic concepts are not covered, to understand batch you'll
need to know about redirection and pipes (< > |), setting and
using environment variables (set this=that, echo %this%), using
command line parameters (%1 to %9) and other stuff. Surf around!


*** How do I write a batch?

Fire up Notepad or any text editor, write your batch, then
save it with a .bat extension - with Notepad select all files
when saving so notepad doesn't tack .txt on the end, or rename
it after saving. Note for Win95 - in Windows Explorer go to
View, Options, make sure hide extensions isn't checked. To run
your batch enter its name from a dos prompt or double-click
it from Windows. Learn some dos first! Be careful since batch
misapplied can reduce your computer to an expensive paperweight
until you reload whatever you wiped out...

To get your batch to run from any directory, put the batch
in a path directory.. enter PATH at a dos prompt for a list.
Modify autoexec.bat to set up your own batch path directory,
for example: PATH C:\windows;C:\Windows\command;C:\batch


*** Where can I get batch information?

The best reference is probably the dos help files, if entering
HELP does nothing look on your Win95 CD in other\oldmsdos. Also
available at Microsoft's web site. It doesn't cover Win95 but
there really isn't much difference.

Batch information on the web...

http://www.maem.umr.edu/~batch/ - Ted Davis' page
http://www.pressroom.com/~tglbatch/ - Tom Lavedas' page
http://www.calweb.com/~webspace/batch/ - Eric's page
http://www.infionline.net/~wtnewton/batch/ - Terry's page
http://purl.oclc.org/net/dirk/batcoll.all - Dirk's bat techniques
http://bigfoot.com/~batfiles/ - Laurence Soucy's page
Questions about dos/Win9x/WinME batch files should be directed
to the alt.msdos.batch newsgroup, WinNT/Win2000 batch questions
should be directed to alt.msdos.batch.nt newsgroup instead.


*** How do I perform if-then-else in batch?

   if not .%1==.help goto else
   rem then commands here
   goto endif
   :else
   rem else conditions here
   :endif

The :else and :endif labels are purely arbitrary, these words
mean nothing to dos. The . in .%1==.help is a dummy character
to prevent syntax error if %1 (the first parameter btw) is empty.
Almost any character on both sides of == will do.

Don't worry too much about if-then-else, batch isn't structured.
if [not] condition statement is about it. But people ask.


*** How do I use the [insert name] command?

Before asking for batch help, please use nameofcommand /? first.
Almost all commands have built-in help. For example...


*** How do I get deltree to work without giving permission?

Typing deltree /? tells us that /y suppresses the confirmation,
so the answer is deltree /y directory


*** How do I delete all files in a dir without giving permission?

The del command has no such switch, so you have to simulate
a Y keystroke...

   echo y | del dirname\*.* > nul

it is recommended that the dirname be hard-coded to avoid data
loss, in case the current directory isn't what you expect.


*** How do I check if a directory exists?

This works for local hard drives...

   @echo off
   if exist c:\windows\nul goto exists
   echo Windows not found
   goto end
   :exists
   echo You've got Windows
   :end

For NT/network compatibility change nul to nul.x, any extension
should do. This technique does not work on removeable drives
like CDROM, for this a more complex solution is needed to avoid
abort-retry-fail or even work at all. Here's one possible
kludge for dos 6/win95 only... (short dir names only)

   :: chkdir.bat dir
   :: sets exists to yes or no
   @echo off
   set exists=yes
   %comspec% /f /c dir /-p %1 | find /i "%1" > nul
   if errorlevel 1 set exists=no

As written, displays error messages if the directory or drive
doesn't exist. The only way I'm aware of fixing that is to add
ctty nul/ctty con statements to the beginning and end of the
procedure, slightly risky since this uses the undocumented /f
switch to automatically fail and if the option isn't available
there would be no way to type 'f' or 'a' to unhang it.


*** How do I set a variable to the contents of a file?

The simplest method of setting a variable to a file uses a
helper file, for the sake of example I'll name it sethelp$

   set result=
Must be a single line without a return at the end! In Notepad type
up to the = then save without pressing return. To set a variable
to a specified ONE line file and return it in %result% use
this batch...
 
   @echo off
   copy sethelp$ + %1 $tmp$.bat > nul
   call $tmp$.bat
   del $tmp$.bat

If running from the path you'll have to hard-code the location
of the sethelp$ file. If incorporating in another batch, change
the %1 to the name of the input file. Note... the file cannot
contain redirection (< > or |) unless enclosed by quotes, a
feature common to all batch input methods.

Here is a similar procedure only it creates its own helper
using the debug command...

   :: Read a specified One line file into 'result'
   @echo off
   > (tmp).bac echo n (tmp).bah
   >>(tmp).bac echo e 100 "set result="
   >>(tmp).bac echo rcx
   >>(tmp).bac echo 0b
   >>(tmp).bac echo w
   >>(tmp).bac echo q
   debug < (tmp).bac > nul
   copy (tmp).bah + %1 (tmp).bat > nul
   call (tmp).bat
   del (tmp).ba?

The "0b" under "rcx" defines the HEX length (11) of the set
line, alter if modifying the length of the variable name. 

Additional file input batches can be found at:
http://www.infionline.net/~wtnewton/batch/batinput.txt
Eric Pement has a page about input methods for batch:
http://www.cornerstonemag.com/sed/bat_env.htm 

To avoid the complexity and problems with batch-only
input methods you might prefer using a utility.


*** How do I set a variable to the output of a program?

Use a technique similar to setting an evar to a file,
except create the temp file using redirection...

   program > tempfile
   call setfile.bat tempfile
   del tempfile

Setfile.bat refers to one of the set-to-file batches.

If the program outputs more than one line, filter through
FIND as in...

   program | find "matchstring" > tempfile etc.


*** How do I extract a line from a file and set a variable to it?

Use the FIND command to extract the line you want to a tempfile
then use your favorite kludge...

   find "matchstring" < input.fil > tempfile
   call setfile.bat tempfile
   del tempfile

Setfile.bat refers to one of the set-to-file batches.
If the line can't be matched with a unique string, you'll
probably need a utility or qbasic/sed/perl routine.


*** How do I get keystrokes from the user or make a menu?

The CHOICE command is used to get single keypresses.
Here is a menu example...

   @echo off
   :menu
   cls
   echo.
   echo       A - Text for item A
   echo       B - Text for item B
   echo       C - End
   echo.
   choice /c:ABC > nul
   if errorlevel 3 goto end
   if errorlevel 2 goto B
   if errorlevel 1 goto A
   echo Error... choice not installed
   goto end
   :A
   echo Commands for item A
   pause
   goto menu
   :B
   echo Commands for item B
   pause
   goto menu
   :end


*** How do I get string input from the user?

This is based on a batch from PC Magazine June 27, 1995, most
other all-batch solutions use FC and DATE in a similar way.
Notes! Don't enter redirection characters (< > |) or errors
will result, possibly overwriting files. If 'enter.bat' exists
in the current directory it will be deleted. It depends on the
English version of dos, change all occurences of 'enter' to
the first word of the date command input prompt to use with
other languages. It does not work with Windows NT.

   @echo off
   echo What's your name?
   :: ... input routine, returns 'str' variable
   > $tmp$.bat fc con nul /lb1 /n|date|find "    1:  "
   > enter.bat echo set str=
   >>enter.bat echo :loop
   >>enter.bat echo if not '%%str%%==' set str=%%str%% %%5
   >>enter.bat echo if '%%str%%==' set str=%%5
   >>enter.bat echo shift
   >>enter.bat echo if not '%%5==' goto loop
   call $tmp$.bat
   del $tmp$.bat
   del enter.bat
   :: ...
   echo Hello %str%!

You might prefer using a utility program instead.


*** How do I concatenate files into one file?

   copy /b *.txt output.fil

If you want separations between the files,
try something like this...

   @echo off
   if .%1==.Loop goto process
   > output.fil rem
   for %%a in (*.txt) do call %0 Loop %%a
   goto end
   :process
   >>output.fil echo.
   >>output.fil echo ----------- File %2 -----------
   >>output.fil type %2
   :end

Modify as needed.


*** How do I start Windows 95 programs or associated files?

   start /w "windows file.ext"

enter start /? for more options.


*** How do I save and restore the current directory?

Here are a pair of batch files written by Tom Lavedas
for saving and restoring the current directory...

   :: Push.bat - Store current folder (directory) name.
   @echo off
   echo @prompt set _Here=$p$_ > %temp%\_temp_A.bat
   %comspec% /e:2048 /c %temp%\_temp_A.bat > %temp%\_temp_B.bat
   call %temp%\_temp_B.bat
   del %temp%\_temp_?.bat

and

   :: Pop.bat - Return to last saved folder (directory).
   @echo off
   %_Here%\
   cd %_Here%

Pop.bat works with long directory names only if they do not
contain a space, for full Windows long name compatibility
change each %_Here% to "%_Here%, the quote tells Windows
it's a long name. Here's a universal modification...

   :: Pop.bat - Return to last saved folder (directory).
   :: Universal version
   @echo off
   ver | find "MS" > nul
   if not errorlevel 1 goto dospop
   "%_Here%\
   cd "%_Here%
   goto popend
   :dospop
   %_Here%\
   cd %_Here%
   :popend

For Push.bat to work properly the 'temp' variable must contain
a valid directory and not end with "\".


*** How do I check the output of a program for a specific string?

   program | find "string" > nul
   if errorlevel 1 goto notfound
   rem string was found
   ...

If the case of "string" isn't known, use find /i "string".


*** How do I rename a file to the current time or date? 

Here are a pair of very clever batch files from Tom Lavedas
for setting the variables 'ptime' and 'pdate', Win9x only...

:: PTime95.bat - A routine for Win 9x that parses the current Time
:: Tom Lavedas <lavedas@pressroom.com>
::             http://www.pressroom.com/~tglbatch/
 @echo %dbgr% off
> {a}.bat echo @prompt set PTime=$_echo $ty $b del call /p $g {a}.bat
> {b}.bat %comspec% /e:2048 /c {a}.bat
> delete.bat echo set PTime=%%PTime%%%Delim2%%%{T}%%
>>delete.bat echo set {T}=%Delim1%
:: long line...
>>delete.bat echo for %%%%v in (0 1 2 3 4 5 6 7 8 9) do if %%1==(Y/N)?%%%%v set {T}=%%%%v
:: end long line
> call for %%v in ({b}.bat {a}.bat set) do call %%v {T}=
  for %%v in ({?}.bat delete.bat) do del %%v
  for %%v in (%For example%) do %%v PTime: %PTime%

and for the date ...

:: PDate95.bat - A routine for Win 9x that parses the current Date
:: Tom Lavedas <lavedas@pressroom.com>
::             http://www.pressroom.com/~tglbatch/
  @echo %dbgp% off
%2 if [%1]==[] %0 DateName ::
:: long line...
> {a}.bat echo @prompt set PDate=$_for %%%%%%%%v in ($d) do set {D}=%%%%%%%%v$_
:: end long line
> {b}.bat %comspec% /e:2048 /c {a}.bat
> call call {b}.bat
> delete.bat echo set PDate=%%PDate%%%Delim2%%%{D}%%
>>delete.bat echo set {D}=%Delim1%
:: long line...
>>delete.bat echo for %%%%v in (0 1 2 3 4 5 6 7 8 9) do if %%1==(Y/N)?%%%%v set {D}=%%%%v
:: end long line
   echo %{D}%y | del call /p > {b}.bat
   set {D}=> nul
   for %%v in ({b}.bat del) do call %%v {?}.bat
   del delete.bat
   for %%v in (%For example%) do %%v PDate: %PDate%

These routines contains long lines that may get wrapped in email,
there should be only one line between the :: symbols where noted.
If not, put cursor at end of 1st line and press space delete.
Also note that there should not be a delete.bat in the current
directory or it will be deleted. <g>

Usage:   call ptime95
         rename thisfile.txt %ptime%.txt
         call pdate95
         md %pdate%
         etc.


*** How do I send keystrokes to a program?

That depends. If it's a program that accepts standard input
(like a dos command or simple utility), and it's ok to also
send an enter character at the end, then all you need to do
is feed it characters using redirection, for example...

   echo YNQ | program

If multiple enter keys are involved, write to a temp first...

   echo.>tempfile                - write a single enter
   echo>>tempfile name           - write "name" + enter
   program < tempfile              (for example)
   del tempfile

To avoid the enter at the end use Notepad or similar to create
a file with exacly the keystrokes you want. If you need to delay
the keystrokes or the program doesn't read from standard input,
you need a key-stuffer utility, look in the archive links.


*** What do all those }{ and $ things mean?

They're uniquely named temp files or variable names. It is
desirable to make the filenames as weird as possible to avoid
overwriting files that happen to have the same name. Also,
confusion is found in spacing and where the redirection
characters are, these all write "hey!" to a temp file...

   echo>[myfile] hey!
   >$$$tmp$$.$ echo hey!
   echo hey! > tempfile


*** Utility programs for batch files

Batch simply wasn't designed to do the kinds of things users
want to do, although us batch hackers ignore this and try to
do them anyway. Batch input routines are especially kludgy
and incompatible, often it's easier to just use a utility
designed for the purpose and avoid the hassle.

SENVAR by Ed Schwartz makes it very easy to set an environment
variable to standard-input... 

   senvar evar                   - input from keyboard
   program | senvar evar > nul   - input from program
   senvar evar < file > nul      - input from file

SENVAR is at http://www.infionline.net/~wtnewton/batch/senvar.txt 

The shareware XSET program by Marc Stern has many extra options,
like reading a file from a specific column and line number... 

   xset /mid 6 2 /line 3 evar < file > nul

XSET is at http://members.tripod.com/~marcstern/xset.htm 

ASET by Richard Breuer, free, makes mathematical operations as
easy as ASET result=2+2, functions for math, string handling,
file/kb input and more. File aset10.zip at Simtel.

Strings by Douglas Boling, free, provides commands for string
handling, modifying memory and master environment, reading files,
math, keyboard input and more. File string25.zip at Simtel.

Many more useful batch utilities can be found at...
Garbo:  http://garbo.uwasa.fi/pc/batchutil.html 
SimTel: ftp://ftp.simtel.net/pub/simtelnet/msdos/batchutl/ 
--------------------------------------------------------------
This is beta 0.36 of the Batch-FAQ, totally subject to change.
Written by Terry Newton, last (majorly) updated March 15, 1999
Minor adjustments April 28, 2003 (sorry no new stuff...) 
Better/more questions and/or answers welcome!