A common question asked by new batch file programmers is "why do we need to double the percent symbols when writing a FOR command?". On the command line %A works fine, so why does a batch need %%A?
To answer this we need to consider all the things in the batch language which use the % symbol:
Now you see the problem this presents, you can have two different types of variable with identical names and the CMD command shell parser needs a way to separate them.
The CMD shell reads through each line of a batch file once from left to right, when it finds a percent sign it checks the next character and proceeds as follows:
- If the next character is another percent sign (%), CMD replaces the two with a single percent sign and then reads the third character evaluating it either as a FOR parameter or, if not in a FOR loop, just treating it as the plain character '%'.
%%G => somevalue
%%Hello => %Hello
- If the next character is a digit (0-9) CMD replaces the percent sign and digit with the value of the corresponding command line parameter. Also if the character is a tilde (~) then Parameter Extensions will be applied.
%1 => somevalue
- If the next character is anything else (so not a number or a % symbol) CMD treats everything up to the next percent sign as the name of a variable and replaces it with the value of that variable.
%_somevariable% => somevalue
When working at the command line (not in a batch script) there is no possibility of any batch file parameters %1, %2 etc so the logic above is not followed and hence FOR parameters on the command line only need a single %.
One other place where a percent character is used is as the modulus operator in the SET /A command, in a batch file this should always be passed as a pair of double %%'s.
It is worth also considering how this affects normal variables - this does not make for readable code, but just to prove a point, lets try to create a standard variable with a variable name that is purely numeric:
You might expect that to create the variable %1%, but in a batch file it will Fail.
Even if the script was called without passing any parameter %1, the parameters take precedence, so %1% is evaluated as %1 plus an extra % at the end. Remember the command line is parsed left to right only once, so the %1 is evaluated before the second % is even read.
You can of course do this at the command line and it will work!
So what have we learned from all this:
- Never try to start a variable name with a number, a common practice is to prefix all variables with an _underscore, if you make a habit of that you will never be bitten by the invalid numeric name issue.
- Don't use numbers as FOR parameter variables, it may work but it will confuse people (and is undocumented).
- If you want to use a plain % symbol anywhere in a batch file, you need to double the %'s
Echo "This includes a 50%% discount"
> This includes a 50% discount
This includes references to filenames, the % is a legal character for a filename, but to access it from a batch file you need to double it:
Start "C:\my work\Demo %% calc.xlsx"
Will open the file Demo % calc.xlsx
If you are aghast at the insanity of all these arcane rules, you should be learning PowerShell, it's awesome!
The caret symbol ^ as the CMD Escape character, has to be doubled both within Batch files and at the command line.
The Batch Line Parser explained on Stack Overflow by Jan Erik (jeb) and Dave Benham, also more on % Expansion (same thread)
Parameters - Command Line Arguments %1 %~f1
Env. Variables - Create/read environment variables.