FOR — Run one command multiple times over a set of values

Synopsis

FOR [/?] [/A[+|-]drash] [/S[+|-]drash] [/R/E/H[+|-]] %%var IN|FROM list [DO] command

Options

/?
Display command syntax information.
/A
Select files by attribute.
/S
Recurse into subdirectories.
/E
Do not display non-fatal error messages.
/R
Disable wildcard expansion.
/H
Exclude "." and ".." when expanding wildcards.

Description

The FOR command iterates over all of the values obtained by processing list executing command once for each value. Everywhere that %var% appears in command, it is replaced with the current value.

The result of the FOR command is the errorlevel returned by the last command that it executes, or 1 if no commands are executed.

How list is processed depends from the verb.

list can comprise either the single element "-" or a list of elements enclosed in brackets. The first form is only valid with the FROM verb.

When list comprises a list of elements enclosed in brackets, it is is treated as a list either of literal values or of search wildcards. If the /R option is used, each list element is used literally as a name. (The /R option is intended for occasions where list does not actually represent a list of search wildcards.) If the /R option is not used, each list element is expanded into zero or more names by searching the relevant directories.

Note: For compatibility with the 16-bit CMD supplied with IBM OS/2, if the /R option is not used any member of list that does not contain any wildcard metacharacters is used literally as a name.

When the /H option is used, the "." and ".." entries will always be skipped when searching directories, even if subdirectories are included by the /A option. This allows the FOR command to be used to iterate all of the "real" subdirectories in a directory.

When the IN verb is used, each name is used as the value to execute command against. When the FROM verb is used, each name denotes a file. The file is read, line by line, using each line in turn as the value to execute command against.

When the FROM verb is used with the special list "-", standard input is read, line by line, using each line in turn as the value to execute command against.

command must be a basic command, and cannot be a pipeline or a sequence of commands. It is not passed through environment variable expansion or redirection processing a second time before being executed. Any redirection, pipeline, or other metacharacters that appear in command, as a result of the environment variable expansion and other parsing of the original command line, are not given any special treatment.

To execute multiple commands for each iteration of a FOR command, use CALL or GOSUB for command in order to execute a separate command script or a subroutine.

Notes on redirection

Redirection takes place only once. Because of the way that the command interpreter works, redirection takes place before the FOR command is invoked. This means that redirection applies to the output of the FOR command as a whole, not to individual invocations of command.

Even if no wildcards match, therefore, redirection will occur. Also, even if redirection is used to truncate and overwrite the original contents of a file with the standard output of the FOR command, the outputs of all invocations of command are treated as one single whole. This is different to the behaviour of the 16-bit CMD supplied with IBM OS/2, but it is more consistent with the operation of the rest of the 32-bit Command Interpreter, in particular with piping the results of a FOR command to the standard input of other commands.

Notes on environment variable expansion

Environment variable expansion takes place only once. Because of the way that the command interpreter works, environment variable expansion takes place before the FOR command is invoked. What the FOR command will "see" as its command line will be the command line after environment variable expansion has taken place.

The most common mistake made is to expect the following command line to append multiple values to PATH:

[c:\]for %%a in (1 2 3) path %PATH%;%%a

This will not happen, however. What the FOR command sees, assuming that the PATH environment variable has the value "\OS2;\OS2\APPS" for the sake of exposition, will actually be:

[c:\]for %a in (1 2 3) do path \OS2;\OS2\APPS;%a

This causes the PATH command to be executed three times. The final PATH command will supercede the previous two, and the PATH environment variable will end up with the value "\OS2;\OS2\APPS;3".

Because environment variable expansion is done before the FOR command is executed, it is not environment variable expansion that causes var to be substituted each time in command. Rather, the FOR command scans command each time that it comes to execute it, and performs a special limited form of environment variable expansion on what it finds.

In whatever command ends up being after environment variable expansion has occurred, FOR looks for, and replaces with the current value obtained from processing set, any instance of var that is :

This may seem complex. At first glance, it would seem necessary to quote all of the necessary percent signs with the escape character, as in:

[c:\]for ^%var in (1 2 3) do echo ^%var^%

But fortunately environment variable expansion has two handy quirks that can make life simpler.

First, an environment variable with an empty name is expanded to a single percent sign. This means that the following will work as expected:

[c:\]for %%var in (1 2 3) do echo %%var%%

In the above command line, "var" is not actually part of any environment variable expansion that occurs, and is just passed as literal text through to what the FOR command actually "sees" when it runs. The actual environment variable expansion is where "%%" is replaced with "%".

The second quirk is that if an environment variable doesn't actually exist, its "value" defaults during environment variable expansion to being the original text before expansion. This means that the following will work as expected:

[c:\]unset /e var
[c:\]for %var% in (1 2 3) do echo %var%

but that the following will result in the variable "b" being used as the iteration variable, and the actual command line that is executed being surprising:

[c:\]set var=b
[c:\]for %var% in (1 2 3) do echo var=%var%

Because the percent sign preceding the initial var is optional, one can avoid the above problem, on the left-hand side of the FOR command at least, simply by not using percent signs at all:

[c:\]for var in (1 2 3) do echo var=%%var%%

Neither the 16-bit CMD supplied with IBM OS/2 nor JP Software's 4OS2 support this obvious syntax extension, however.

This quirk also causes the "single-percent" version of the FOR command to work as expected. The reason, bizarrely, is that this version of the FOR command ends up trying to expand environment variables with very unlikely names.

For example, in the following command, environment variable expansion ends up looking for an environment variable named "var in (1 2 3) do echo " and, unsurprisingly, not finding a variable with that name simply passes the original text on verbatim, so that the FOR command sees the original percent signs:

[c:\]for %var in (1 2 3) do echo %var

One final point:

The variable used as the iteration variable is not an environment variable, but is, rather, only a syntactic placemarker, to show what parts of command should be modified for each different value obtained from set. If an environment variable exists with the same name, it is not affected by the FOR command in any way, and will retain its original value.

This is the same behaviour as that of the 16-bit CMD supplied with IBM OS/2, which can be demonstrated by running the following command line:

[c:\]for %%v in (1 2 3) do set v

It is not the same behaviour as that of JP Software's 4OS2, which does not work the same way as the 16-bit CMD supplied with IBM OS/2 in this instance. JP Software's 4OS2 modifies the environment variable (if its name is more than one letter long), which can be demonstrated by running the following command line in 4OS2:

[c:\]for %%var in (1 2 3) do set var

In contrast to the behaviour of JP Software's 4OS2, the 32-bit Command Interpreter simply extends the original behaviour of the 16-bit CMD supplied with IBM OS/2 in the previous example, to operating the same way with multiple-letter variable names.

CALL EXTPROC GOTO GOSUB IF RETURN CANCEL QUIT EXIT


The 32-bit Command Interpreter is © Copyright Jonathan de Boyne Pollard. "Moral" rights are asserted.