Windows Batch Files

external links: index. projects. home

in-file links: preamble- shift- for- set- echo- errorlevel- strings- reference- end


This is just some personal notes, as I use batch files, sometimes called command files, to do lots, and LOTS of things ... the command 'CMD /?' will list some of the things available in the command prompt, and how it can be run with some switches ... NOT everything is there, and there are some limitations, but batch file represent a simple but quite powerful 'script' language ... a link to the full Microsoft referenceis given below.

Of course a batch file can run other programs, applications, including other batch file. But to avoid exiting the current batch file, other batch file should be 'called', like 'call batch2'. Batch files will have either a '.BAT', or '.CMD' extension ... They are plain ASCII text, and can be created with most editors ...

Normally lines in the batch file are echoed to the console, unless the batch file starts with '@echo OFF' - this can later be turned on with '@echo ON', or the command is preceded with an '@'. So '@echo OFF' will turn off all line echoes in the batch file script, until 'echo ON' is encountered, while the use of the '@' can selectively hide certain lines while others can be shown. Also '::' can be used to prohibit certain lines from display ...

Parameters entered are seen as %1, %2, ... %9 inside the batch file, and they can have GOTO labels, which always start with a colon, ':', so you can test for user parameter input as follows -

@if "%1." == "." goto HELP
@echo You entered %1 %2 %3 %4 %5 ...
@goto END

@echo You need to enter the file name, or something ...
@goto END


The %0 is the batch file name.

Note: If a semicolon, ';' or an equal sign (=) is used as a command line argument to a batch file, it is treated as a blank space. For example, in the following test.bat batch file -

@echo %0 %1 %2 %3 


> test a=b 3 

will output

a b 3 

The only way to get around this behaviour is to encase the argument in double quotes, like

> test "a=b" 3 4 

will output - note the double quotes AREincluded -

test "a=b" 3 4

If greater than nine (9) parameters are entered, then these can be accumulated using shift , as shown below.

The full set of special characters that usually/sometimes require quotes is: <space> &()[]{}^=;!'+,`~At least the set &<>()@^|are always special, sometimes even inside double quotes (") ... Quoting from the 'SET' command reference - "The characters <, >, |, &, ^are special command shell characters, and they must be preceded by the escape character ( ^) or enclosed in quotation marks when used in String(for example, "StringContaining&Symbol"). If you use quotation marks to enclose a string that contains one of the special characters, the quotation marks are set as part of the environment variable value."

This special interpretation of certain characters sometimes makes batch file use IMPOSSIBLE ;=(( 



This command moves %2 into %1, and so on up the list, and thus can be used to accumulate more than the nine (9) entered parameters, which can be directly addressed through %1 - %9 ... Note the addition of a '.' in the compare. Some past command processors did not do well with 'empty' strings, like ""! Example :-

@set TEMPSC=%1
@if "%1."=="." goto GOTCMD
@goto CYCLE
Action %TEMPSC%  

This would accumulate all the entered parameters into the variable TEMPSC, then pass all to the particular action ...


FOR command

The generic form is ' for %%i in (set) do command %%i [params]' ...

But if the command is multiple lines, then 'calling' a label can be used ...

@for %%G in (set) do (@call :label %%G)
@if "%1." == "." goto :EOF
@action1 %1
@cmd /C action2 %1 - This would be processed in a new shell ...
goto :EOF

With token in a file (like HTML Tidy) testcases.txt
426885 1
427633 0
427662 1
to process tokens per line from the file, (as is HTML Tidy test/alltest1.cmd file) try -

for /F "tokens=1*" %%i in (testcases.txt) do call onetest.cmd %%i %%j

If the 'token' in the file are of the form -
as found in a spencer1.tests file in a GNU grep test file, then the following will split these -

@for /F "delims=@ tokens=1,2,*" %%i in (spencer1.tests) do echo %%i %%j %%k

And interesting site - has lots more ... found using a Yahoo! search for 'windows for command syntax' ...


SET - Using SET increment a counter ...

To increment say a test counter, try -

@REM Initialise the count variable ...
@set TEMPCNT=1

Then later, to bump this counter by the numeric value 1 -

@set /a TEMPCNT+=1

Numeric Values: Numeric values are decimal numbers unless prefixed by 0? for hexadecimal numbers or 0 for octal numbers. Therefore, 0?2 is the same as 18, which is the same as 022.

The following table lists the operators supported for /ain descending order of precedence.

Operator Operation performed
( ) Grouping
! ~ - Unary
* / % Arithmetic
+ - Arithmetic
<< >> Logical shift
& Bitwise AND
^ Bitwise exclusive OR
| Bitwise OR
= *= /= %= += -= &= ^= |= <<= >>= Assignment
, Expression separator


ECHO <string>

Basically this prints (echoes) the stringto standard output, or into a pipe, if followed by a pipe char. '|', and adds a new line. If followed by a full stop, like @echo. it will just output an empty line.

The following batch file searches the current directory for files with the .txt file name extension, and displays a message indicating the results of the search. It also shows the powerful 'IF <something> ( do this ) ELSE ( do that )' switch :-

@echo off
if NOT EXIST *.txt (
echo This directory contains no text files.
) else (
   echo This directory contains the following text files:
   dir /b *.txt

If no .txt files are found when the batch file is run, the following message displays:

This directory contains no text files.

If .txt files are found when the batch file is run the following output displays (for this example, assume the files File1.txt, File2.txt, and File3.txt exist):

This directory contains the following text files:

A simple pipe example would be, This echoes the string 'abc' into a 'pipe' (|), read by Findstr, which reads the pipe as input and returns result whether the string begins with first the letter 'a', which is does, so returns 0, then b, which is does not, so returns 1 :-

@echo abc|Findstr /b /c:a > nul
@echo Exit code = %ERRORLEVEL% ...
@echo abc|Findstr /b /c:b > nul
@echo Exit code = %ERRORLEVEL% ...

The output from such a batch file should be -

Exit code = 0 ...
Exit code = 1 ...  



In a batch file %ERRORLEVEL% retrieves the EXIT CODE of the last action. This 'exit code' may then be used to 'switch' actions ... example :-

goto answer%errorlevel%
echo Program had return code 1
goto end
echo Program had return code 0
goto end
echo Done! 

It should be NOTED that the following batch script


will compare ERRORLEVEL with 1 OR GREATER, 2, 3, etc - that is GEQ ... To be more specific, one of the 3 letter 'compare' operators must be used, like - note it can be used in upper or lower case, with or without '%' around it :-

@if %errorlevel% LEQ 1 goto okay

The set of 3 letter operators is -
EQU= Equal to,
NEQ= Not equal to,
LSS= Less than,
LEQ= Less than or equal to,
GTR= Greater than, and
GEQ= Greater than or equal to.


STRINGS - Maniplating strings in batch files

A simple string counter

@echo off & setlocal EnableDelayedExpansion
set Var=finding the length of strings
for /l %%A in (0,1,10000) do if not "%Var%"=="!Var:~0,%%A!" (set /a Length+=1) else (echo !Length! & pause & exit /b)

will output

Press any key to continue . . .

Split string at a specific character, like here '-'

@echo off
setlocal enableDelayedExpansion
set "str=45-abc"
set ^"lead=!str:-=^

set lead=%lead%
echo "!lead!"
echo %lead%

will output


Cut a string at a specific position

@echo off
set str=politic
echo Whole: %str%
set str=%str:~0,3%
echo First 3: %str%

will output

Whole: politic
First 3: pol

Split into letters, placed in a numbered variable. Not also get char count.

@echo off
setlocal EnableDelayedExpansion
@REM set str="hello world^!"
set str=hello bye
set tempstr=%str%
set count=0
if not defined tempstr goto DONE
    set tempstr=%tempstr:~1%
    set /a count+=1
    set /a pos=%count%-1
    set t!count!=!str:~%pos%,1!
    goto loop
echo Count of letters in "%str%": %count%
set count2=0
if !count2! GEQ !count! goto END
 set /a count2+=1
 set var=t!count2!
 echo %count2% of %count%: %var% = !%var%!
 goto loop2
echo eof %count2% %count%

will output

Count of letters in "hello bye": 9
1 of 9: t1 = h
2 of 9: t2 = e
3 of 9: t3 = l
4 of 9: t4 = l
5 of 9: t5 = o
6 of 9: t6 =
7 of 9: t7 = b
8 of 9: t8 = y
9 of 9: t9 = e
eof 9 9


Command Reference

For most commands, entering the command followed by /? may yield some help text, and does cmd /?. Some other specific command pages - for and if .

The full Windows 'command reference' can be viewed online at Microsoft TechNet... or a zip, in the form of a self extracting EXE, can be downloaded from here- if either of these links are invalid, as they can change over time, (they were valid as of May 2008), then go to the main MSsite, and search for 'command reference' should yield the new links ...


checked by Tidy   Valid XHTML 1.0 Transitional