home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / vrac / tsbat46.zip / BATRICKS.TXT < prev    next >
Text File  |  1994-09-04  |  35KB  |  936 lines

  1. Assorted Batch Tricks                                 Sun 4-Sep-94
  2. =====================
  3.                                                All rights reserved
  4.                             Copyright (c) 1993, 1994 by Timo Salmi
  5.  
  6. ..................................................................
  7. Prof. Timo Salmi      Co-moderator of comp.archives.msdos.announce
  8. Moderating at garbo.uwasa.fi anonymous FTP  archives  128.214.87.1
  9. Faculty of Accounting & Industrial Management; University of Vaasa
  10. Internet: ts@uwasa.fi   BBS +(358)-61-3170972; FIN-65101,  Finland
  11. ..................................................................
  12.  
  13.   ┌───────────────────────────────────────────────────────────┐
  14.   │ This file belongs to TSBAT*.ZIP. Please do not distribute │
  15.   │ this batricks.txt file separately!                        │
  16.   └───────────────────────────────────────────────────────────┘
  17.  
  18. Introduction
  19. ============
  20.  
  21. This file contains assorted batch tricks. Many, but not all, have
  22. been used in the TSBAT*.ZIP collection of batches. Likewise, there
  23. are some useful further tricks, not documented here, to be found in
  24. the TSBAT batches. Furthermore, many users have sent me useful
  25. suggestions and their own alternative solutions. My best thanks for
  26. the material. You can find much of this feedback stored in the
  27. garbo.uwasa.fi:/pc/pd2/tspost*.zip files.
  28.  
  29. You are free to quote brief passages from this file provided you
  30. clearly indicate the source with a proper acknowledgment.
  31.  
  32. Comments and corrections are solicited. But if you wish to have
  33. individual batch programming consultation, please rather post your
  34. question to a UseNet newsgroup like comp.os.msdos.programmer. It is
  35. much more efficient than asking me by email. I'd like to help, but I
  36. am very pressed for time. I prefer to pick the questions I answer
  37. from the Usenet news. Thus I can answer publicly at one go if I
  38. happen to have an answer. Besides, newsgroups have a number of
  39. readers who might know a better or an alternative answer. Don't be
  40. discouraged, though, if you get a reply like this from me. I am
  41. always glad to hear from fellow batch file users.
  42.  
  43.  
  44. INDEX
  45. =====
  46.  
  47. 1)  Making "@echo off" general
  48. 2)  Deleting all files
  49. 3)  Nested loops
  50. 4)  Checking whether a directory exists
  51. 5)  Checking that a program is available at the current directory or at path
  52. 6)  Using subroutines in batches
  53. 7)  Convert a parameter to uppercase
  54. 8)  Appending a new directory to the path
  55. 9)  Comparing two files
  56. 10) Writing an empty line
  57. 11) Customizing the pause message
  58. 12) Complicate renaming with for
  59. 13) Checking for wildcards
  60. 14) Preventing breaking the batch
  61. 15) Prevent a break from bypassing your autoexec.bat
  62. 16) Getting the extension
  63. 17) The quote character %
  64. 18) Eliminating auxiliary batches
  65. 19) Utilizing the subst command in paths
  66. 20) How to run a batch once a week (testing for the weekday)
  67. 21) Testing if a file name includes a path
  68. 22) Showing the time without enter
  69. 23) Alternatives for testing for the errorlevel value
  70. 24) Redirecting a batch file's output
  71. 25) Testing for environment space sufficiency
  72. 26) A simple trick to "disable" a drive
  73. 27) Sending an escape sequence to the printer
  74. 28) Creating a random string
  75. 29) Finding out the length of a string
  76. 30) How to obtain the MsDos version into an environment variable
  77. 31) Finding out the number of regular files on a drive
  78. 32) Augmenting line numbers to a text file
  79. 33) Storing and returning to the original directory (push and pop)
  80. 34) Enticing the current date into an environment variable
  81. 35) Identifying the individual PC
  82. 36) For loop and redirection quirks
  83. 37) Traversing a directory tree
  84. 38) Echoing the redirection symbol
  85. 39) Getting the file basename
  86.  
  87.  
  88. 1. Making "@echo off" general
  89. =============================
  90.  
  91. If you want to turn the echo off, and do not wish to show that line
  92. on the screen, you can easily do this by applying
  93.  @echo off
  94.  
  95. There is a catch, however, because this only works since MsDos
  96. version 3.30.  So if you want to make it general, put the following
  97. line in your autoexec.bat file if you are using MsDos 3.30 or higher
  98.  set _echo=@
  99. Then use the following format in your batches, which will then work
  100. for any MsDos version
  101.  %_echo%echo off
  102.  
  103.  
  104. 2. Deleting all files
  105. =====================
  106.  
  107. One of the most Frequently Asked Questions (FAQs) about batches is
  108. how to suppress the "Are you sure (Y/N)?" confirmation requirement
  109. for del *.*.  Use the following:
  110.  echo y| del *.*
  111. If you wish to suppress the message too, use
  112.  echo y| del *.* > nul
  113. Whether or not it is sensible to suppress the confirmation can be
  114. debated, but this is the trick anyway.
  115.  
  116.  
  117. 3. Nested loops
  118. ===============
  119.  
  120. It is possible to have nested loops of a kind in batch programming.
  121. Consider the following two batches, and try it out by calling
  122. test.bat.
  123.   echo off
  124.   rem TEST.BAT
  125.   for %%f in (a b c d e f) do %comspec% /c test2 %%f
  126.  
  127.   echo off
  128.   rem TEST2.BAT
  129.   for %%g in (1 2 3) do echo %1%%g
  130.  
  131. Alternatively write everything below on a single line
  132.   for %%f in (a b c d e f) do %comspec% /c
  133.     for %%g in (1 2 3) do echo %%f%%g
  134. (The wrap has been used in the text is because of the right margin.
  135. Don't wrap your batch.).  The disadvantage of this alternative is
  136. that the echo will be on.
  137.  
  138.  
  139. 4. Checking whether a directory exists
  140. ======================================
  141.  
  142. It is sometimes useful to be able to test whether a particular
  143. directory exists. The following test is true if the %1 directory
  144. does not exist.
  145.  if not exist %1\nul if not exist %1nul echo Directory %1 does not exist
  146.  
  147.  
  148. 5. Checking that a program is available at the current directory or at path
  149. ===========================================================================
  150.  
  151. When you call a program from a batch, and do not give the explicit
  152. path to it, it is advisable to test that the program is available
  153. either at the current directory or the default path.
  154.   set _found=
  155.   if exist %1 set _found=yes
  156.   for %%d in (%path%) do if exist %%d\%1 set _found=yes
  157.   for %%d in (%path%) do if exist %%d%1 set _found=yes
  158.   if "%_found%"=="yes" goto _continue
  159.   echo %1 is not at path or the current directory
  160.   goto _out
  161.   :_continue
  162.   echo %1 found at path or in the current directory
  163.   :_out
  164.  
  165.  
  166. 6. Using subroutines and recursion in batches
  167. =============================================
  168.  
  169. It is possible to use subroutines within batches. The crucial trick
  170. is setting an environment variable (eg _return) to point to a label
  171. where to return after the subroutine has been performed. For an
  172. example see UNPACK.BAT, and BOOT.BAT, the sections :_common and
  173. :_subru.
  174.  
  175. Likewise it is possible to use recursion go emulate subroutines in
  176. batches. (Recursion means that a batch calls itself).
  177. As an example see SAFEDEL.BAT and trace the effects of the line
  178.  for %%f in (%1) do call safedel %%f recurse
  179. Note that safedel could be replaced by %0 because the zeroeth
  180. parameter of a batch file points to itself.
  181.  
  182.  
  183. 7. Convert a parameter to uppercase
  184. ===================================
  185.  
  186. This example shows how to ensure that the parameter %1 given to the
  187. batch is in uppercase. This utilizes the fact that MsDos converts
  188. the path to uppercase. The result is stored in upcase_ and then the
  189. original path is restored.
  190.   set tmp_=%path%
  191.   path=%1
  192.   set upcase_=%path%
  193.   path=%tmp_%
  194.   set tmp_=
  195.  
  196. The also is another method for getting case-independent results.
  197. This is adapted from Jeff Prosise's column in PC Computing, March
  198. 1993, pp. 216-217. If the batch below is called TEST.BAT, it makes
  199. no difference whether you enter "TEST yes" or "TEST YES" or "TEST
  200. yEs".
  201.   @echo off
  202.   if not "%1"=="" set %1=*****
  203.   set status_=
  204.   if "%yes%"=="*****" set status_=yes
  205.   if "%no%"=="*****" set status_=no
  206.   if not "%status_%"=="" echo The parameter %%1 was a %status_%
  207.   if "%status_%"=="" echo The parameter %%1 was neither a yes nor a no
  208.   if not "%1"=="" set %1=
  209.  
  210.  
  211. 8. Appending a new directory to the path
  212. ========================================
  213.  
  214. This often needed trick is basically very simple. For example
  215. to add directory %1 to path use
  216.  path=%path%;%1
  217. Note that you can only use this trick in a batch. It will not work
  218. at the MsDos prompt because the environment variables are expanded
  219. (%path%) only within batches.
  220.  
  221. For a full treatment with safeguards against appending non-existing
  222. directories, or appending twice, see ADDPATH.BAT.
  223.  
  224.  
  225. 9. Comparing two files
  226. ======================
  227.  
  228. It is possible in batch programming to test whether or not two files
  229. have identical contents. This trick utilizes th external MsDos
  230. programs fc.exe and find.exe.  (An external MsDos program means, of
  231. course, a program that comes with the standard MsDos releases. Most
  232. often the MsDos external support files are located in a c:\dos
  233. directory.)
  234.   fc %1 %2 > tmp$$$
  235.   type tmp$$$ | find /i "fc: no differences encountered" > diffe$$$
  236.   if exist notsame$ del notsame$
  237.   copy diffe$$$ notsame$ > nul
  238.   if not exist notsame$ echo Files %1 and %2 are different
  239.   if exist notsame$ echo Files %1 and %2 are identical
  240.   if exist tmp$$$ del tmp$$$
  241.   if exist notsame$ del notsame$
  242.   if exist diffe$$$ del diffe$$$
  243. If you think about, this idea can be used for other useful purposes,
  244. too, because it establishes whether a given string is found in a
  245. text file.
  246.  
  247.  
  248. 10. Writing an empty line
  249. =========================
  250.  
  251. This is a simple, but an often needed, useful trick.  Just use echo
  252. with (for example) a point (.) after it. As you can see, I have
  253. utilized this batch feature extensively in my batch collection.
  254.  echo.
  255.  
  256.  
  257. 11. Customizing the pause message
  258. =================================
  259.  
  260. You can easily customize the message given by pause by giving your
  261. own with echo and directing the pause message to nul.
  262. to nul.
  263.  echo Break to quit, any other key to remove the tmp directory
  264.  pause > nul
  265.  
  266.  
  267. 12. Complicate renaming with for
  268. ================================
  269.  
  270. Although this is basically trivial, one does not necessarily come to
  271. think of it. The for statement is quite useful for involved renaming
  272. of files. An example delineates. For example I have the following
  273. files (Turbo Pascal units for TP 4.0, 5.0, 5.5, 6.0 and 7.0).  Say
  274. that I wish to rename them to be version 33 instead of 32.
  275.   tspa3340.zip
  276.   tspa3350.zip
  277.   tspa3355.zip
  278.   tspa3360.zip
  279.   tspa3370.zip
  280. The following for-statement does that conveniently.
  281.  for %f in (40 50 55 60 70) do ren tspa32%f.zip tspa33%f.zip
  282. Naturally, renaming is not the only task that can utilize this
  283. trick. I am sure you can readily think of others, like
  284.   for %d in (a b) do format %d:
  285.  
  286.  
  287. 13. Checking for wildcards
  288. ==========================
  289.  
  290. This example shows how you can test whether a parameter (%1) of a
  291. batch contains wildcards.
  292.   @echo off
  293.   for %%f in (%1) do if "%%f"=="%1" goto _nowilds
  294.   echo Parameter %1 contains wildcards (or is missing)
  295.   :_nowilds
  296.  
  297.  
  298. 14. Preventing breaking the batch
  299. =================================
  300.  
  301. It is possible to prevent the user from interrupting a batch by
  302. using the ctty command to reassign the input (and the output)
  303. device. Here is an example (an elementary password batch requiring
  304. inputting an e). Note the < and > redirections which are needed
  305. while the ctty has been assigned to nul. The ask batch enhancer is
  306. included in the TSBAT collection.
  307.   @echo off
  308.   ctty nul
  309.   echo Now you cannot break the batch with ^C or ^Break > con
  310.   :_ask
  311.   echo Use e to break > con
  312.   ask /b /d < con
  313.   if errorlevel==101 if not errorlevel==102 goto _out
  314.   goto _ask
  315.   :_out
  316.   ctty con
  317.   echo Back to normal. Now you can break the batch with ^C or ^Break.
  318. Note that this trick does not prevent you from rebooting with
  319. alt-crtl-del while the batch is running. For that you need an
  320. external program like noboot.exe from garbo.uwasa.fi:/pc/ts/
  321. tstsr17.zip (or whichever version number is current).
  322.  
  323.  
  324. 15. Prevent a break from bypassing your autoexec.bat
  325. ====================================================
  326.  
  327. You can actually prevent a quick tapping of the break from bypassing
  328. your autoexec.bat by a variation of the trick in the item above. Put
  329. for example
  330.   shell=c:\command.com /p nul
  331. in your config.sys. Before you do, make sure to have a floppy to
  332. boot from in case something goes wrong. I first saw trick when it
  333. was posted in the UseNet comp.os.msdos.programmer newsgroup by
  334. Joseph Gil yogi@cs.ubc.ca.
  335.  
  336. This is not, however, quite all there is to it.  You should put
  337.   ctty con
  338. as the last line to your autoexec.bat.  If you don't, the keyboard
  339. will not be responding, and you must boot from the floppy you so
  340. sensibly had prepared :-).
  341.  
  342.  
  343. 16. Getting the extension
  344. =========================
  345.  
  346. It would be quite useful to be able to extract the extension of a
  347. given file name into an environment variable. Or to be able just to
  348. test whether there is an extension. Here is how to do that. The
  349. batch is based on the information in PC-Magazine July 1992, Vol 11,
  350. No. 13, page 528. It gives the crucial information that if one
  351. precedes the argument of a for loop with a slash (/), then the
  352. argument is interpreted in two parts. The first part is the first
  353. character of the argument, the second part all the rest. Neat,
  354. indeed.
  355.    The problem with my solution below is that it will not recognize
  356. .* or .??? as extensions. But, of course, one can first test for
  357. wildcards as shown in a previous item "Checking for wildcards". See
  358. e.g. UNPACK.BAT for the utilization of this method.
  359.      @echo off
  360.      set exten_=%1
  361.      :_next
  362.      set prev_=%exten_%
  363.      for %%f in (/%exten_%) do set exten_=%%f
  364.      if ".%exten_%"=="%prev_%" goto _extfound
  365.      if not "%exten_%"=="%prev_%" goto _next
  366.      goto _noext
  367.      :_extfound
  368.      echo The filename %1 has an extension %exten_%
  369.      goto _out
  370.      :_noext
  371.      echo The filename %1 has no extension
  372.      :_out
  373.      set exten_=
  374.      set prev_=
  375.  
  376.  
  377. 17. The quote character %
  378. =========================
  379.  
  380. As we know %1 indicates the first parameter given to a batch. Thus
  381. for example echo %1 echoes that parameter.  But what if you want to
  382. echo the actual string %1 instead.  The % character acts as a quote
  383. character. Thus echo %%1 will indeed be a "%1" instead of its usual
  384. interpretation. Try the following simple test
  385.   @echo off
  386.   if "%1"=="" goto _out
  387.   echo %1
  388.   echo %%1
  389.   :_out
  390. See the item on "Eliminating auxiliary batches" for utilizing this
  391. feature. A good example of utilizing this feature is given by
  392. DELPATH.BAT.
  393.  
  394.  
  395. 18. Eliminating auxiliary batches
  396. =================================
  397.  
  398. Quite a number of batch programming tasks require an auxiliary batch
  399. which the primary batch has to call. Many of these cases can be
  400. eliminated by making the batch call itself (a kind of recursion).
  401. The auxiliary code is put in the batch itself. The trick is best
  402. illustrated by looking at the SHOW.BAT, which provides a wild-carded
  403. TYPE command, and would normally need an auxiliary file to type each
  404. of the individual files. Another example is given by the SAFEDEL.BAT
  405. batch.
  406.    There is also an another trick for a similar purpose. The primary
  407. batch creates and auxiliary batch or batches, which it then calls.
  408. See DELPATH.BAT for an example of this method. Here is also a simple
  409. demonstration listing the drives on your system.  (Only from c to t,
  410. actually because of the wrap I use here).
  411.  @echo off
  412.  echo @echo off> tmp$$$.bat
  413.  echo if exist %%1:\nul echo Drive %%1: is present>> tmp$$$.bat
  414.  for %%d in (c d e f g h i j k l m n o p q r s t) do call tmp$$$ %%d
  415.  del tmp$$$.bat
  416.    There was an inventive twist of this method in PC-Magazine August
  417. 1992, Vol. 11, No. 14, p. 527 for getting the volume label of a
  418. disk.  Here is my own example using the same techniques. It sets the
  419. current directory in an environment variable getdir_. I have
  420. utilized this technique in PUSHDIRE.BAT.
  421.   @echo off
  422.   echo @echo off> director.bat
  423.   echo set getdir_=%%2>> director.bat
  424.   echo echo %%getdir_%%>> director.bat
  425.   dir | find "Directory"> go.bat
  426.   call go
  427.   if exist director.bat del director.bat
  428.   if exist go.bat del go.bat
  429.  
  430.  
  431. 19. Utilizing the subst command in paths
  432. ========================================
  433.  
  434. I use the following kind of a simple batch to make some of my
  435. directories easy to reach. The way this simple batch is written it
  436. avoids unnecessary errors if the substitution already has been made.
  437. As a last measure it shows the current substitution status.
  438.   @echo off
  439.   if exist m:\nul echo The substitution has already been made
  440.   if not exist m:\nul subst m: c:\math
  441.   if not exist s:\nul subst s: c:\support
  442.   subst
  443.  
  444.  
  445. 20. How to run a batch once a week (testing for the weekday)
  446. ============================================================
  447.  
  448. The crucial trick is to be able to put the weekday into an
  449. environment variable. For the full treatment see WEEKLY.BAT. The
  450. essential trick needed is below, that is capturing the weekday into
  451. a weekday_ environment variable. No auxiliary programs outside the
  452. normal MsDos commands are needed.
  453.   @echo off
  454.   echo.| date | find "Current" > tmp$$$.bat
  455.   echo set weekday_=%%3> current.bat
  456.   call tmp$$$
  457.   echo %weekday_%
  458.   if "%weekday_%"=="Fri" echo Thank God it's Friday
  459.   if exist tmp$$$.bat del tmp$$$.bat
  460.   if exist current.bat del current.bat
  461.   set weekday_=
  462. In fact, if you substitute %%4 for the %%3 in the above, you'll
  463. capture today's date. Neat, eh?
  464.  
  465.  
  466. 21. Testing if a file name includes a path
  467. ==========================================
  468.  
  469. First of all please see the earlier item "Getting the extension"
  470. because the same ideas are drawn upon. Testing whether the file name
  471. is a bare file name like go.exe or includes a path like
  472. r:\progs\go.exe is quite a complicated task if one wants to allow
  473. wildcarded names like r:\progs\*.exe.  This can be done, and here is
  474. how.  If one can figure this one out, one can safely say that one
  475. has begun to understand batch files.
  476.   @echo off
  477.   echo @echo off> tmp$$$.bat
  478.   echo set rest_=%%1>> tmp$$$.bat
  479.   echo :_next>> tmp$$$.bat
  480.   echo set prev_=%%rest_%%>> tmp$$$.bat
  481.   echo for %%%%g in (/%%rest_%%) do set rest_=%%%%g>> tmp$$$.bat
  482.   echo if ":%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
  483.   echo if "\%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
  484.   echo if not "%%rest_%%"=="%%prev_%%" goto _next>> tmp$$$.bat
  485.   echo goto _nopath>> tmp$$$.bat
  486.   echo :_found>> tmp$$$.bat
  487.   echo set haspath_=yes>> tmp$$$.bat
  488.   echo goto _out>> tmp$$$.bat
  489.   echo :_nopath>> tmp$$$.bat
  490.   echo set haspath_=no>> tmp$$$.bat
  491.   echo :_out>> tmp$$$.bat
  492.   echo set rest_=>> tmp$$$.bat
  493.   echo set prev_=>> tmp$$$.bat
  494.   for %%f in (%1) do call tmp$$$ %%f
  495.   if "%haspath_%"=="yes" echo Filename %1 includes a path
  496.   if "%haspath_%"=="no" echo Filename %1 does not include a path
  497.   rem if exist tmp$$$.bat del tmp$$$.bat
  498.   set haspath_=
  499.  
  500.  
  501. 22. Showing the time without enter
  502. ==================================
  503.  
  504. A simple trick to show the current time:
  505.   echo.| time | find /v "new"
  506. For capturing the time into an environment variable see
  507. LASTBOOT.BAT.
  508.  
  509.  
  510. 23. Alternatives for testing for the errorlevel value
  511. =====================================================
  512.  
  513. Many programs and some MsDos commands (like diskcomp, format and
  514. xcopy) return an errorlevel exit code on termination. Testing for
  515. the errorlevel is complicated by the cumulative nature of
  516. errorlevels. Thus if you wish to test if the errorlevel was
  517. (exactly) 2, you must use
  518.  if errorlevel==2 if not errorlevel==3 echo Errorlevel 2
  519. Another alternative is utilizing the for command:
  520.  for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set _errlev=%%e
  521.  if "%_errlev%"=="2" echo Errorlevel 2
  522. Alternatively, and more generally
  523.  for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set _errlev=%%e
  524.  if "%_errlev%"=="2" echo Errorlevel %_errlev%
  525. A convenient trick in more complicated batches is using the goto
  526. command:
  527.   for %%e in (0 1 2) do if errorlevel==%%e goto _label%%e
  528.   goto _out
  529.   :_label0
  530.   echo Errorlevel 0
  531.   :_label1
  532.   echo Errorlevel 1
  533.   :_label2
  534.   echo Errorlevel 2
  535.   :_out
  536. See BOOT.BAT for actual usage of this technique.
  537.  
  538.  
  539. 24. Redirecting a batch file's output
  540. =====================================
  541.  
  542. Output from within a batch file is easily redirected. Consider a
  543. batchfile example.bat with the following contents
  544.   @echo This is a redirection test> test
  545. Running "example" will produce a file "test" with
  546.   This is a redirection test
  547. The line has an eoln (end of line: ascii 13 + 10) at the end.
  548. Note that it often is advisable not to leave any blank in front of
  549. the > redirection operator.
  550.  
  551. Redirecting the output that a batch produces, is more complicated.
  552. Consider a batchfile example2.bat with the following contents
  553.   @echo This is another redirection test
  554. Running
  555.   example2 > test
  556. will produce an empty "test" file, while the text is echoed on the
  557. standard output. To redirect the output, you need to drive the batch
  558. through the command interpreter command.com like this (provided that
  559. command.com is at path or in the current directory).
  560.   command /c example2 > test
  561. This will redirect the text to the "test" file.
  562.  
  563. There is another quirk of redirection in MsDos batch programming
  564. best demonstrated by an example:
  565.   @echo off
  566.   rem This line will create an empty tmp.$$ file > tmp.$$
  567.   :: This line will not create an empty tmp.$$$ file > tmp.$$$
  568.   rem This line will cause problems: Press <ESC>
  569.   :: This line will not cause problems: Press <ESC>
  570. As explained in PC Magazine Vol 12, Number 9, November 9, 1993, the
  571. reason is that the :: is taken as a label and not processed while
  572. the rem basically is an MsDos command that will be processed. The
  573. processing will start from the redirection at the end. This is the
  574. the also reason why redirection and the MsDos FOR command will cause
  575. problems. (See the entry "For loop and redirection quirks".)
  576.  
  577.  
  578. 25. Testing for environment space sufficiency
  579. =============================================
  580.  
  581. If your batch utilizes environment variables there is a possibility
  582. that you run out of environment space.  If you get an "Out of
  583. environment space" message the well-known trick to increase your
  584. environment space by using shell configuration in config.sys:
  585.   Example: shell=c:\bin\command.com c:\bin /e:1024 /p
  586.  
  587. A perhaps less-known trick is that you can test in advance if your
  588. batch will run out of environment space. Below is an example showing
  589. you how to test if you have an additional 32 bytes of environment
  590. space still available for your batch:
  591.  @echo off
  592.  set test_=12345678901234567890123456789012
  593.  if "%test_%"=="12345678901234567890123456789012" goto _yes
  594.  echo Insufficient environment space
  595.  goto _out
  596.  :_yes
  597.  echo Sufficient environment space
  598.  set test_=
  599.  rem Whatever you wish to do
  600.  :_out
  601.  
  602.  
  603. 26. A simple trick to "disable" a drive
  604. =======================================
  605.  
  606. It you wish temporarily disable a drive use the subst command for
  607. example as follows
  608.   @echo off
  609.   md c:\none
  610.   subst d: c:\none
  611. To enable it again use
  612.   @echo off
  613.   subst d: /d
  614.   rd c:\none
  615.  
  616.  
  617. 27. Sending an escape sequence to the printer
  618. =============================================
  619.  
  620. Here is a truly trivial trick. You cannot send escape sequences to
  621. the printer directory from the command line, but it is quite easy to
  622. do that from a simple batch file:
  623.   @echo ESC%1> prn
  624. where you have to replace the ESC by the true escape character using
  625. your preferred editor. One snag with this methods is that it imposes
  626. a linefeed.
  627.  
  628.  
  629. 28. Creating a ramdom string
  630. ============================
  631.  
  632. I was asked on the UseNet news how to create a ramdom string. My
  633. reply.  Please study the following example and expand on it
  634.   @echo off
  635.   echo 10 randomize(val(mid$(time$,7,2))) > tmp.bas
  636.   echo 20 open "tmp2.bat" for output as #1 >> tmp.bas
  637.   echo 30 x$ = mid$(str$(int(rnd*10000)),2) >> tmp.bas
  638.   echo 40 print #1,"@set ramdom_=";x$ >> tmp.bas
  639.   echo 50 close #2 >> tmp.bas
  640.   echo 60 system >> tmp.bas
  641.   gwbasic tmp.bas
  642.   call tmp2
  643.   del tmp.bas
  644.   del tmp2.bat
  645.   set
  646.  
  647.  
  648. 29. Finding out the length of a string
  649. ======================================
  650.  
  651. The task of finding out the length of a string was tackled in PC
  652. Magazine January 26, 1993 issue. The solution is my own and more
  653. general, but naturally it has similar ingredients to the PC
  654. Magazine's.
  655.   @echo off
  656.   set test_=Testing the length of a string
  657.   echo %test_% > len$&$&$
  658.   dir len$&$&$ | find "LEN$&$&$" > go$$$.bat
  659.   echo @echo off> len$&$&$.bat
  660.   echo set length_=%%1>> len$&$&$.bat
  661.   call go$$$
  662.   echo The length is %length_% bytes
  663.   del len$&$&$
  664.   del len$&$&$.bat
  665.   del go$$$.bat
  666.  
  667.  
  668. 30. How to obtain the MsDos version into an environment variable
  669. ================================================================
  670.  
  671. Here is the code how to do it.
  672.   @echo off
  673.   ver > go$$$.bat
  674.   echo @echo off> ms-dos.bat
  675.   echo set version_=%%2>> ms-dos.bat
  676.   call go$$$
  677.   echo Your MsDos version is %version_%
  678.   del go$$$.bat
  679.   del ms-dos.bat
  680.  
  681. MsDos 5.0 version introduced many enhancements (like the loadhigh
  682. command, etc) and additions to the command switches (like /B and /S
  683. to the DIR command). Therefore it is useful to be able to test
  684. whether the batch is being run on a system taht is at least MsDos
  685. 5.0. Below is one option.
  686.   rem Establish whether MsDos version 5.0 or later is being used
  687.   set isver50_=
  688.   ver | find "5.0" > tmpfind.$$$
  689.   ver | find "6.0" >> tmpfind.$$$
  690.   ver | find "6.2" >> tmpfind.$$$
  691.   copy tmpfind.$$$ tmpfind1.$$$ > nul
  692.   del tmpfind.$$$
  693.   if exist tmpfind1.$$$ set isver50_=yes
  694.   if exist tmpfind1.$$$ del tmpfind1.$$$
  695.  
  696.  
  697. 31. Finding out the number of regular files on a drive
  698. ======================================================
  699.  
  700. Try
  701.   attrib /s c:\*.* | find /c "\"
  702. The directories will not be (mis)counted as files as would with the
  703. dir command. Besides the dir command is not recursive until MsDos
  704. version 5.0.
  705.   Note that if you do this for the same drive where you reside,
  706. you'll get one too many in the count because of the "|" pipe.
  707.  
  708.  
  709. 32. Augmenting line numbers to a text file
  710. ==========================================
  711.  
  712. Occasionally it might be useful to put line number to a text file.
  713. Here is an example how to do it with MsDos commands only
  714.   type YourFile.txt | find /v /n "&$&$&$123" > YourNew.txt
  715. The parameter &$&$&$123 stands for an improbable string, since find
  716. /v means displaying all the lines not containing it.
  717.  
  718.  
  719. 33. Storing and returning to the original directory (push and pop)
  720. =================================================================
  721.  
  722. There are several methods for (non-resident) pushing and popping the
  723. directory by bacth file techniques. In other words storing the
  724. current directory, changing the directory in between, and then
  725. returning to the starting directory. PUSHDIRE.BAT and POPDIRE.BAT
  726. give one method where the current drive and directory are stored in
  727. environment variables. The second method, displayed below, is a
  728. direct adaptation from Jeff Prosise's column in PC Computing, March
  729. 1993, pp. 216-217. Later the trick was presented again in Pc
  730. Magazine June 14, 1994, Vol. 13, No. 11, p. 357. The method is a
  731. very clever utilization of the prompt system. An example
  732. illustrates.
  733.   @echo off
  734.   echo @prompt cd $p$_$n:> r:\setback.bat
  735.   %comspec% /c r:\setback> r:\goback.bat
  736.   ::
  737.   rem Change the drive and directory
  738.   c:
  739.   cd \dos
  740.   echo The current directory is
  741.   cd
  742.   rem Do whatever you wish to do there
  743.   pause
  744.   ::
  745.   rem Go back to the original drive and directory
  746.   call r:\goback
  747.   echo Now back in the original directory
  748.   ::
  749.   rem cleanup
  750.   if exist r:\setback.bat del r:\setback.bat
  751.   if exist r:\goback.bat del r:\goback.bat
  752.  
  753.  
  754. 34. Enticing the current date into an environment variable
  755. ==========================================================
  756.  
  757. Like in the item "Storing and returning to the original directory"
  758. there are more than one way of doing this. One method is indicated
  759. in the item "How to run a batch once a week". The other (again)
  760. utilizes the prompt:
  761.   @echo off
  762.   echo @prompt set date_=$d> r:\tmp$$$.bat
  763.   %comspec% /c r:\tmp$$$> r:\tmp2$$$.bat
  764.   call r:\tmp2$$$
  765.   echo %date_%
  766.   del r:\tmp$$$.bat
  767.   del r:\tmp2$$$.bat
  768.  
  769. If you look at your MsDos manual for the prompt special $ codes
  770. (like $d) that you can use in the prompt, you'll see that this
  771. method opens quite a number of possibilities of putting information
  772. into environment variables. Execise: Put the current weekday into an
  773. environment variable. Hint: Apply $d and $h.
  774.  
  775.  
  776. 35. Identifying the individual PC
  777. =================================
  778.  
  779. In cases of some batches it is useful to identify the PC the batch
  780. is run on. For example I use several different PCs myself and
  781. occasionally I need to differentiate between them. The solution is
  782. really trivial. Set an environment variable in the autoexec.bat to
  783. designate the PC. I use a variable pcid_ for this purpose. An
  784. outline batch illustrates.
  785.   @echo off
  786.   if "%pcid_%"=="" goto _none
  787.   goto %pcid_%
  788.   :dell
  789.   echo Dell 325N laptop, do whatever
  790.   goto _out
  791.   :trifu
  792.   echo Trifunic 386 desktop, do whatever
  793.   goto _out
  794.   :karvi
  795.   echo "Garfunkel" Pinus 486 desktop, do whatever
  796.   goto _out
  797.   :_none
  798.   echo PC not identified, do whatever
  799.   :_out
  800. For example in the autoexec.bat of my DELL 325N laptop I have
  801.   set pcid_=dell
  802.  
  803.  
  804. 36. For loop and redirection quirks
  805. ===================================
  806.  
  807. A question from Newsgroups: comp.os.msdos.misc,comp.os.msdos.programmer
  808. > I am using DOS 5.0 and I have the following line in my batch file:
  809. > for %%f in (a b c d) do if exist %%f echo put %%f >> tmpfile
  810. > where a,b,c,d are some filenames.
  811. >
  812. > What I expect it to do is to echo the lines
  813. >  put a
  814. >  put b
  815. >  put c
  816. >  put d
  817. > into the file tmpfile.
  818. >
  819. > But what happen is after the "put a" is written to tmpfile, the rest of the
  820. > lines will just echo to the screen, look like that the redirection is not
  821. > working.
  822. >
  823. > If I take away the "if exist" everything is working fine.  I found out
  824. > every time when I use a conditional statement with redirection, it will
  825. > only redirect the first time, the rest will echo to the screen.
  826. >
  827. > Is it the for loop cannot be mixed with the conditional statement and the
  828. > redirection?
  829.  
  830. Yes, it can be mixed, but not so simply in this case. Use the
  831. following batch
  832.   @echo off
  833.   del tmpfile
  834.   for %%f in (a b c d) do if exist %%f call auxil %%f
  835. where auxil.bat contains
  836.   @echo off
  837.   echo put %1>> tmpfile
  838. I'll be darned if I know why :-).
  839.  
  840. In fact it is possible to do this with a single batch by employing
  841. the following method described in an earlier item
  842.   @echo off
  843.   echo @prompt echo put %%%%1$g$g tmpfile> tmp$$$.bat
  844.   %comspec% /c tmp$$$> auxil.bat
  845.   if exist tmpfile del tmpfile
  846.   for %%f in (a b c d) do if exist %%f call auxil %%f
  847.   del tmp$$$.bat
  848.   del auxil.bat
  849.  
  850.  
  851. 37. Traversing a directory tree
  852. ===============================
  853.  
  854. Traversing it straight up is relatively easy as can be seen from
  855. this example.
  856.   @echo off
  857.   :_loop
  858.   dir/w
  859.   if not exist ..\nul goto _out
  860.   cd ..
  861.   goto _loop
  862.   :_out
  863. Going recursively down through a directory and its subdirectories is
  864. very complicated. Yet it can be done if you have MsDos 5.00 or
  865. beyond. The SWEEP.BAT bacth accompanying tsbat*.zip demonstrates
  866. how. The method is, however, too difficult to be of real practical
  867. importance. It is getter to use an auxiliary program for sweeping,
  868. like garbo.uwasa.fi:/pc/filefind/target15.zip or SWEEP.COM from
  869. /pc/pcmagvol/vol4n24.zip.
  870.  
  871.  
  872. 38. Echoing the redirection symbol
  873. ==================================
  874.  
  875. In certain situations would be useful to be able echo the
  876. redirection symbol rather than have its perform its redirection
  877. function. For example your batch file might have a help line like
  878. this
  879.   echo The line to customize is "echo dir/w %%%%3\%%2 >> %%new_%%"
  880. As you see the double quotes pre-empt the redirection. If you left
  881. them out, the line would result create a file %NEW_% containing
  882. "The line to customize is echo dir/w %%3\%2".
  883.    Contrary to Unix, \ cannot be used to cover the special meaning
  884. of a symbol. As explained in the item "The quote character %" the %
  885. sign, can as is demonstrated above by the %% pairs. But %> does not
  886. take precedence over the redirection.
  887.  
  888.  
  889. 39. Getting the file basename
  890. =============================
  891.  
  892. Occasionally one needs to get the file name without the extension.
  893. Just like getting the extension from a file name using the "for %%f
  894. in (/%exten_%)" trick, even this can be done with batch commands
  895. only. The batch code for getting the basename has been presented by
  896. Neil Rubenking in PC Magazine April 26, 1994, Vol. 13, No. 8. But
  897. enough is enough even with batch tricks. The logic is getting overly
  898. complicated. One has to draw the line somewhere, stop kidding
  899. oneself, and start using batch enhancers (extenal programs to help
  900. out). I think here the limit has been reached. Hence I have included
  901. "basename" and "basepath" programs, which you can use to create the
  902. enhancers. They return the relevant information into an environment
  903. variable with that name.
  904.    When you come to think of it. From one viewpoint, what else than
  905. batch enhancers are all the external MsDos commands (usually) in
  906. your C:\DOS directory?
  907.    Using basename and basepath is very easy. Below is an example
  908.        @echo off
  909.        basename r:\cmand\command.com
  910.        basepath r:\cmand\command.com
  911.        echo %basename%
  912.        echo %basepath%
  913. You can discard the environment variable simply by applying (note
  914. the two alternatives):
  915.        set basename=
  916.        basepath
  917. There is also a "basexten" batch enhancer in the /pc/ts/tsbat*.zip
  918. collection.
  919.  
  920.  
  921. Literature
  922. ==========
  923.  
  924. Most books on batch programming, which I have seen, are too
  925. elementary to be really useful to the readers of this file. Hence
  926. this list is very brief indeed.
  927.  
  928. Jamsa, Kris (1993). Concise Guide to MS-DOS Batch Files. Microsoft
  929.   Press. (Draws heavily on DEBUG, but might be of general interest
  930.   to you.)
  931.  
  932. Some issues of magazines like the PC Magazine and PC Computing have
  933. contained much useful MsDos lore. But they have gradually become so
  934. heavily Windows oriented that they are losing their interest and
  935. usefulness to an MsDos user.
  936.