Batch File Programming: Stupid Useless Tricks


Coming under the heading of the "Edison Effect": Thomas Edison could have been the father of electronics when he discovered the electron cloud surrounding heated filaments, but he dismissed it as merely a curiosity. We all bump into curious items, but never pursue thier practical application...


Prefacing commands with +

Also works with commas and semicolons. Generally causes the command to treat it's last letter as it's first argument. For example, +MD will create a directory named D. One exception is echo. It treats the entire word as it's first argument.
N:\temp>dir
Volume in drive N is HDA1_BOOT 
Volume Serial Number is 32FF-2953 
Directory of N:\temp

.  <DIR> 04-17-97 3:24p . 
.. <DIR> 04-17-97 3:24p .. 
0 file(s) 0 bytes 
2 dir(s) 2,215,936 bytes free
N:\temp>+md
N:\temp>dir
Volume in drive N is HDA1_BOOT 
Volume Serial Number is 32FF-2953 
Directory of N:\temp

.  <DIR> 04-17-97 3:24p . 
.. <DIR> 04-17-97 3:24p .. 
D  <DIR> 04-17-97 3:24p d 
0 file(s) 0 bytes 
3 dir(s) 2,215,424 bytes free
N:\temp>+echo hello 
echo hello

Display Windows Revision

Use the undocumented /R option on the VER command.
C:\>ver
Windows 95. [Version 4.00.950]
C:\>ver /r
Windows 95. [Version 4.00.950] 
Revision A 
DOS is in HMA

Display Error Levels

Use the undocumented /Z option on COMMAND
N:\temp>command /z
Microsoft(R) Windows 95 
(C)Copyright Microsoft Corp 1981-1995. 
Return code (ERRORLEVEL): 0 
WARNING: Reloaded COMMAND.COM transient
N:\temp>echo test|find "test">nul 
Return code (ERRORLEVEL): 0
N:\temp>echo qwerty|find "test">nul 
Return code (ERRORLEVEL): 1
N:\temp> exit

N:\temp>

Change Floppy Serial Numbers

Use DEBUG to change data on the disk

This example shows how to "turn off" the serial number display for the disk in the A: drive. The digit shown in blue on the "E" command is the one that toggles display of the serial number.
C:\>DEBUG
-L 0 0 0 1
-E 26 00
-W 0 0 0 1
-Q

C:\>DIR A:

Volume in drive A has no label
Directory of A:\

This example shows how to set the serial number for the disk in the A: drive to any value. Notice the numbers you enter (in red) are mirrored from the serial number you'll get.
C:\>debug
-L 0 0 0 1
-E 26 29 78 56 34 12
-W 0 0 0 1
-Q

C:\>DIR A:

Volume in drive A has no label
Volume Serial Number is 1234-5678
Directory of A:\


Using MORE to Concatenate

MORE is the only command I know that accepts two input methods at once. While MORE is usually used with piping or redirection, it can also be supplied with a filename. If you supply both, MORE will "page" both , so you must be careful the combined length will not exceed a page (or you'll be forced to press a key). Notice with the sample files I generated below how MORE places a CR/LF pair at the beginning of each file, but leaves the ends alone.
 
Generation of sample files used in this example
E:\>copy con now.txt 
Now is the time 
for all good men^Z
        1 file(s) copied
E:\>copy con to.txt 
to come to the aid 
of their country^Z 
        1 file(s) copied 





Although my example used
type now.txt|more to.txt
the same results are achieved with
more<now.txt to.txt


Using ATTRIB to Search for a File

ATTRIB with the /S option will search all subdirectories for the designated files. This is much faster than the method of using FIND on the output of DIR /S /B. In fact, it runs about twice as fast as the Windows 95 "Find Files or Folders" function. In addition, it always returns the short "8.3" filename. Frustratingly, it also returns the short path appended to the long filename. For example:
H:\>attrib /s longf*.*
  A   HR     LONGFI~2.TXT  H:\VB5\MSDEVE~1\Long File Name.txt
There is a temptation to use ATTRIB as a long-to-short filename converter. Unfortunately, the attributes do get displayed first. So you can't be sure what position your filename will be in because you don't know how many attributes there are. Since long file names can contain spaces, you can't just start at the end and work backwards either. The good news is that ATTRIB sets errorlevels based on whether or not it found files. So you can at least use it like a recursive IF EXIST:
attrib /s \somefile.txt
if not errorlevel 1 echo I found "somefile.txt" somewhere on the disk

Surviving Abort, Retry, Fail

If you invoke the undocumented /F option on COMMAND, it will automatically answer "F" to any Abort, Retry, Fail? questions. This eliminates the fear of your program hanging if you reference a floppy that isn't inserted. Although the questions are answered automatically, they still appear on screen...
C:\WINDOWS>COMMAND /F
Microsoft(R) Windows 95
   (C)Copyright Microsoft Corp 1981-1995.
C:\WINDOWS>DIR A:
Not ready reading drive A 
Abort, Retry, Fail?
Not ready reading drive A 
Abort, Retry, Fail?Volume in drive A has no label
Not ready reading drive A 
Abort, Retry, Fail?Fail on INT 24
C:\WINDOWS>if exist a:\nul echo hello
Not ready reading drive A 
Abort, Retry, Fail? 
Not ready reading drive ? 
Abort, Retry, Fail? 
C:\WINDOWS> exit
C:\WINDOWS>

Redirection based on IF EXIST

If you use IF EXIST (or IF NOT EXIST) without the required command, you can specify a file for the next command (prompt and all) to be redirected into. Notice the command gets redirected, not the command's output. The redirection only occurs when the IF condition is true and if echo is on. If the condition is false or echo is off, a zero-byte file is generated instead. The bad news is that this only works on Win95 and Win98.
echo on
@if exist nul > test.txt
echo off
In the above example, since NUL always exists, TEST.TXT will contain the string C:\>echo off. Although nobody does it this way, this has obvious applications in capturing prompts without launching a separate DOS shell:
@ctty nul 
prompt set value$Q 
echo on 
if exist nul>temp.bat
hello 
echo off 
prompt $p$g 
ctty con
When the above file is run, it will create a TEMP.BAT with the text set value=hello in it. The ctty nul hides the Bad command or file name error that happens because "hello" is not a valid command.


TRUENAME Simplifies complex paths

Some batch programs may arrive at a path by appending \.. to move around. Afterwards, it may not be clear just where DOS thinks things are. The undocumented TRUENAME command will resolve and simplify 8.3 names whether the files or directories they reference exist or not. TRUENAME even sees through SUBST and JOIN (like anybody uses them nowadays). In the examples below, all commands were entered from the E:\> prompt. The responses all refer to the C: drive.
E:\>TRUENAME C:\PROGRA~1\WINZIP\..\..\WINZIP\PROGRA~1\NUL
C:/NUL
E:\>TRUENAME C:\PROGRA~1\WINZIP\..\..\WINZIP\PROGRA~1\README.TXT
C:\WINZIP\PROGRA~1\README.TXT
E:\>TRUENAME C:\PROGRA~1\WINZIP\..\WINZIP\README.TXT
C:\PROGRA~1\WINZIP\README.TXT
The bad news is that TRUENAME absolutely will not work with long file names. It simply truncates the names until they fit in an 8.3 mask, and will happily give you the bogus name as a result. The good news is that if you change into a directory, running TRUENAME without arguments will give you the real legitimate short name of the directory.


Instant Environment Space

If you need to set lots of environment variables, but you're not sure if there's going to be enough space left for them, you're faced with a tough problem. You have to use the /E option on SHELL in your CONFIG.SYS or with COMMAND to boost your environment space beyond the standard 256 bytes. All well and good on your machine. But if you write for others, maybe they already have a 1024 byte environment. Normally, when you use COMMAND to launch another session, you get a copy of the current environment. But there's an easy way to stop that! Run COMMAND specifying the path for COMMAND.COM (you forgot about that option, didn't you!). You don't have to specify a valid path, but you can if you want to.
E:\>set 
TMP=C:\WINDOWS\TEMP 
TEMP=C:\WINDOWS\TEMP 
PROMPT=$p$g 
winbootdir=C:\WINDOWS 
COMSPEC=C:\WINDOWS\COMMAND.COM 
PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;C:\UTILS; 
windir=C:\WINDOWS
E:\>command . 
Specified COMMAND search directory bad
Microsoft(R) Windows 95
   (C)Copyright Microsoft Corp 1981-1995.
E>set 
PATH=
E>exit
E:\>command c:\windows
Microsoft(R) Windows 95 
   (C)Copyright Microsoft Corp 1981-1995.
E>set 
PATH=
E>exit
E:\>
If you have a heavy-duty batch file, you can call it this way:
command \ /c test.bat
Be careful using this technique, because the entire environment is gone (until you exit). That means no PATH. No access to any commands not in the current directory. You might want to make a copy of the PATH before you jump into the clean session. Notice in the example code below I used "noenvironment" as the command search path. It makes it a little more self-documenting.
@echo off
echo Here is the original environment:
set
echo @echo off > test.bat
path >> test.bat
echo echo. >> test.bat
echo echo Here is the clean environment: >> test.bat
echo set >> test.bat
command noenvironment /c test.bat
del test.bat

ECHOing the words ON and OFF

Echo is often used to create secondary batch files, Basic files, and user prompts. Very rarely, you'll need to echo a line that starts with on or off. If so, you can expand on a trick used to create blank lines. You probably already know that echo. (echo followed by a period with no space between) will result in a blank line, but did you know that you can substitute any of these five characters / \ [ ] + instead of the period as well? It turns out that echo followed by any of those six characters will result in echo treating on and off as simple words:
E:\>echo on error goto done
ON

E:\>echo.on error goto done
on error goto done

E:\>echo on

E:\>echo.on
on

E:\>echo off - opposite of on
OFF

E:\>echo.off - opposite of on
off - opposite of on

Running DOS 5 & 6 Under Windows 95

Now, this is the stupidest thing you could ever want to do. The only time I ever do it is when I want a quick test of some obsolete feature for a compatibility check. Otherwise I reboot my machine (I love System Commander!) into the appropriate OS. Still, to quote Douglas Adams, it's "Mostly harmless". You can see by the picture that I am running 5 different versions of DOS simultaneously. Try not to do too much unless you like seeing Incorrect DOS version on every other command. All you need to do is copy and rename your command.com files ( I picked DOS500, DOS600, etc.). Then use SETVER to put the new names in the version table, for example

setver dos500.com 5.00
setver dos600.com 6.00
setver dos620.com 6.20
setver dos622.com 6.22
After you reboot, you'll be able to use the old versions of DOS simultaneously just like I do. Just don't try to run them from the command line or you'll lock up your DOS window. Either double-click them with Explorer, put them in your Start Menu, or use START from the command line to run them in a separate window.


Get Everything Before Something Else
No, there is no better way to describe it. If you have a string like 2:34:56.78p and you want to take action based on everything before the first colon, you can do it without parsing it character-by-character. The only restriction is that the "colon" has to be one of these ten special characters:  [  :  ,  .  /  \  ;  + =  ]    What you do is GOTO to a label in your program and use the string as the specified destination. Except it won't actually go there. It only reads up to the first special character. Suppose I had these two batch files:

::TEST1.BAT
@echo off
call test2.bat 2:34:56.78p

::TEST2.BAT
@echo off
goto LBL%1
:LBL
echo I didn't go to a label!
goto DONE
:LBL1
echo At label 1
goto DONE
:LBL2
echo At label 2
goto DONE
:DONE

When TEST1 runs, it calls TEST2, passing it 2:34:56.78p as an argument. TEST2 then has a GOTO command which you might think would get interpreted as GOTO LBL2:34:56.78p The amazing thing is that it actually goes to LBL2! Everything from the colon on to the right got ignored! So this is a way to make a jump in your program based on a drive letter, hour, month or who knows what else.



 
 
 

Lost? Look at the site map.

Bad links? Questions? Send me mail.

Google
Yahoo
Ask Jeeves