The percent-sign %
is used by cmd.exe
and also its predecessor command.com
to mark expansion1 of environment variables (like %VAR%
), for
-loop meta-variables (like %I
/%%I
), and argument references in batch files (like %1
).
There are two distinct parsing modes, which behave differently when it comes to %
-expansion:
- Command line mode:
- There are no command line arguments, hence no argument references are supported.
- Empty (undefined) variables are not expanded, meaning that
%VAR%
is kept as is when an environment variable VAR
is not set.
- There is no escaping of
%
-signs supported, so %%VAR%%
results in %
+ value of VAR
+ %
.
- Batch file mode:
- Batch files may have arguments, which are expanded by argument references like
%1
.
- Empty (undefined) variables are expanded to a blank string.
- Escaping of the
%
-sign is supported in that %%
represents a literal %
.
Of course I cannot tell why the developers decided the parser to behave that way, but I believe there are several factors contributing:
- The command line mode existed before batch file mode, the latter of which required introduction of support for arguments, which in turn led to the demand to let the parser distinguish between variable or argument references.
- When the
for
command was introduced2, the developers decided to use the %
-sign too to mark loop meta-variables, leading to conflicts in command line mode, particularly because empty variables remain: For instance, an expression like %foo%bar
results in the value of foo
+ bar
when variable foo
is set, but otherwise to value of %f
+ oo
+ value of %b
+ ar
when loop variables %f
and %b
exist, and so on. This is particularly because for
parses the command line a second time after the initial potential expansion of environment variables.
- Introduction of batch file mode and the conflicts coming from the
for
parser probably led to the decision of improved handling of %
-expansion in that undefined variables are treated differently by expanding such to empty strings. In order to still be able to yield literal %
-symbols, escaping like %%
was introduced: For example, a text like 10% plus 20%
could not be returned without escaping since a variable named SPACE + plus 20
is most likely undefined; however, specifying 10%% plus 20%%
results in the literal string 10% plus 20%
.
Anyway, the %
-escaping in batch file mode is the intrinsic reason for why for
meta-variables need to be specified like %%I
(in contrast to %I
in command line mode) in order for them to survive the escaping, resulting in %I
, which is then recognised by the for
command parser that comes into play after %
-expansion.
For detailed information about what exactly happens, refer to: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
1) The term expansion means to replace an expression (like %VAR%
) by the string value it refers to (like the one stored in the respective environment variable named VAR
) while parsing.
2) Although I do not know whether the for
command was introduced before or after implementation of the batch file mode.