Scripting in Windows NT, part 2

In part 2 of this series on creating efficient scripts in Windows NT 4.0, Richard Charrington discusses the for statement—which has been significantly enhanced by the introduction of command extensions.

In “Scripting in Windows NT, part 1 ,” I examined special characters, subroutines, and the if statement. In this Daily Drill Down, I’ll describe the for statement, which has been greatly enhanced by the introduction of command extensions in Windows NT 4. I’ll conclude this installment with the replace statement.

The for statement
In part 1, the last example showed how to use for in its simplest form. The syntax for this form is
for %%variable in (set) do command
I’ve shown the double-percent characters because I’m assuming that you’ll be writing scripts. Remember that the second percent character is not needed when executing this command on the command line.

The variable can be any character (as in %%i, %%x, %%v, etc.) and is case sensitive. However, there are a couple of limitations. Only the letters A-Z and a-z can be used, and only 26 variables can be defined, or in use, at any one time.

The set parameter of the for statement can have more than one form. In this for statement, set can be a file or set of files (wildcards may be used). It can also be a list of items.

Here are some examples:
for %%i in (*.*) do command [command-parameters]for %%i in (file1, file2, file3) do command [command-parameters]for %%i in (1,2,3,4,5) do command [command-parameters]
In the first case, command will be executed for every file in the current directory.

In the second case, command will be executed for each file in the list (that is, three times).

In the last case, command will be executed five times.

The variable—in this case %%i—is set to each value in set in turn. To make this useful, [command-parameters] usually includes %%i. For example:
for %%i in (c:\windows\*.txt) do (echo %%i & type %%i)
This means, For each file matching*.txt in the c:\windows directory, display its name, then display its contents.

Command extensions
Command extensions bring a whole new world to this useful, but fairly limited, command. I’ll start with the most useful of the new forms:
FOR /L %%variable IN (start,step,end) DO command [command-parameters]
Finally, the for statement provides what it does in all other programming languages. The equivalent in BASIC is
FOR i=start TO end STEP step..........NEXT i
In C, this would be
for(i=start;i<=end;step){       .....       .....}
At first, the NT script version would seem to be a bit more limiting—there’s no NEXT statement or braces to enclose a list of commands to execute. However, this problem is easily overcome by the use of the subroutine, which we discussed in part 1. So, we can do the following:
for %%i in (1,10,1) do call :Commands %%igoto Continue:Commandsecho %1echo This is iteration number %1....and so on....goto :EOF :Continue..........
Here, the goto :EOF statement is equivalent to the NEXT statement in BASIC.

At this point, you may be wondering about something. In my last example, in the for statement I use the variable %%i, which takes on the values assigned in set. Yet, in the “subroutine,” I use the positional variable %1. Remember, in my description of the call :Label statement in part 1, I stated that it works just like the call batchfile statement. You can therefore append in the called code variables or strings that can be referred to by positional variables.

The next most useful new form introduced with command extensions is the ability to use a file, or files, to provide a list of tokens to use. Both the most complicated and the most powerful of the for forms, it uses the following format:
FOR /F ["options"] %%variable IN (filenameset) DO command [command-parameters]
filenameset is one or more filenames. Each file is opened, read, and processed in order, before moving on to the next. Processing consists of reading in each line, parsing each line into tokens according to the settings in "options", and setting %%variable and any other variables to the relevant tokens before executing the command [command-parameters]part of the statement. By default (no "options" used), %%variable is set to the first blank separated word of each line.

Options are enclosed in quotes (to allow the use of spaces and other special characters that could be interpreted by the command processor). The "options" parameter may consist of one or more of the following:
  • eol=c—c is a character that begins a comment. All characters following this, up to the end of the line, are ignored.
  • skip=n—Skip n lines at the start of each file.
  • delims=xxx—Specifies a delimiter set that replaces the default of space and tab.
  • tokens=x,y,m-n—Specifies which tokens from each line are to be made available to the body of the for statement. If the last token is specified as an asterisk, then an additional variable is assigned the remaining part of the line after the last token is parsed.

The first three of these options are fairly self-explanatory, but the tokens option may need some examples to make it clearer:
for /f "tokens=2,1,3* delims=, " %%i in (testfile.csv) do echo %%i. %%k %%j, %l
If testfile.csv contained the following:

Deakins,Mr,John,Chief Astronomer

Smith,Mrs,Julia,Master Mathematician


the above example would produce
Mr. John Deakins, Chief AstronomerMrs. Julia Smith, Master MathematicianMr. Albert Einstein, Mathematician, Philosopher, Genius
This is the way it works: Tokens are words separated by commas and/or spaces (delims=, ). The code starts by assigning %%i the second token. It assigns %%j the first token, %%k the third token, and %%l everything following the third token.

The example could also have been written
for /f "tokens=1-3* delims=, " %%i in (testfile.csv) do echo %%j. %%k %%i, %l
A final use of the for /f form is to parse the output of a command. The command is placed in single quotes between the brackets, as in
for /f "delims=\ tokens=2*" %%i in ('dir c:\winnt /b /s') do echo %j
This code will display every file in every directory in c:\winnt. It will display the full path of each file, except C:\WINNT\.

The next for form is
FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
This form walks the directory tree specified after the /R option, executing the for statement in each directory. If no directory is specified, then the current one is assumed. set can be just a period (.), in which case %%variable will be set to each directory in the tree in the form c:\windows\system\.

Here’s an example:
for /r c:\ %%i in (*.tmp) do @echo %%i
This is equivalent to the command dir c:\*.tmp /s, except that, instead of echo %%i you could write del %%i, or type %%i, whereas with the dir command there is no way to “get at” the file found.

Notice that I use the @ character before the echo statement. This stops the statement from being displayed before the result, so it keeps the output nice and clean.

The final form of the for statement is
FOR /D %%i IN (set) DO command [command-parameters]
This is almost identical to the original form, except that if set contains wildcards, they are matched against directories rather than files.

Finally, when using %%variable, it is worth noting that the command extensions have introduced powerful enhancements for modifying what the variable produces. In the following examples, I’ll use a single % sign (up to now I’ve used two):

%~fi Expands %i to a fully qualified pathname.
%~di Expands %i to the drive letter only.
%~pi Expands %i to the path only.
%~ni Expands %i to the filename only.
%~xi Expands %i to the file extension only.
%~si Expanded path contains short names only.
%~$PATH:i Searches the directories in the PATH environment variable for %i and expands %i to the first one found. An empty string is returned if PATH is not defined or the file is not found by the search.

These modifiers can be combined to produce the desired result:

%~dpi Expands %i to drive letter and path.
%~nxi Expands %i to filename and extension.

One important point here—which seems obvious once stated—is that when using these qualifiers, you must not have a variable name that conflicts with them.

The replace statement
The replace statement allows you to replace (or renew or refresh) files in a particular directory with those in another. This statement is probably one of the least useful of the NT command set. There is nothing that replace can do that cannot be achieved just as easily with xcopy (which I’ll cover in part 4 of this series). The syntax of the command is
REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/P] [/R] [/W]REPLACE [drive1:][path1]filename [drive2:][path2] [/P] [/R] [/S] [/W] [/U]
[drive1:][path1]filename Specifies the source file or files.
[drive2:][path2] Specifies the directory where files are to be replaced.
/A Adds new files to destination directory. Cannot use with /S or /U switches.
/P Prompts for confirmation before replacing a file or adding a source file.
/R Replaces read-only files as well as unprotected files.
/S Replaces files in all subdirectories of the destination directory. Cannot use with the /A switch.
/W Waits for you to insert a disk before beginning.
/U Replaces (updates) only files that are older than source files. Cannot use with the /A switch.

In this Daily Drill Down, I’ve discussed how you can use the for and replace statements in NT scripting. In part 3 of this series, I’ll cover three commands: set, call, and shift. You may think set and shift are innocuous commands, but they can be used to great effect. The call command, along with command extensions, gives you the ability to use subroutines in batch scripts.

Richard Charrington’s computer career began when he started working with PCs—back when they were known as microcomputers. Starting as a programmer, he worked his way up to the lofty heights of a Windows NT Systems Administrator, and he has done just about everything in between. Richard has been working with Windows since before it had a proper GUI and with Windows NT since it was LANManager. Now a contractor, he has slipped into script writing for Windows NT and has built some very useful auto-admin utilities.

The authors and editors have taken care in preparation of the content contained herein, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.

Editor's Picks

Free Newsletters, In your Inbox