What is the difference between % and %% in a cmd file?

I recently included a line similar to this in a .cmd file:

for /f %%f in ('dir /b .\directory\*.sql') DO sqlcmd -b -o ".\directory\output\%%f.txt" -i ".\directory\%%f"

Originally I had only used %f, and it would work fine when run on the command line, but not when run through the file. When I switched to %%f, it worked in the file. Just wondering what the difference is.


Solution 1:

(Explanation in more details can be found in an archived Microsoft KB article.)

Three things to know:

  1. The percent sign is used in batch files to represent command line parameters: %1, %2, ...
  2. Two percent signs with any characters in between them are interpreted as a variable:

    echo %myvar%

  3. Two percent signs without anything in between (in a batch file) are treated like a single percent sign in a command (not a batch file): %%f

Why's that?

For example, if we execute your (simplified) command line

FOR /f %f in ('dir /b .') DO somecommand %f

in a batch file, rule 2 would try to interpret

%f in ('dir /b .') DO somecommand %

as a variable. In order to prevent that, you have to apply rule 3 and escape the % with an second %:

FOR /f %%f in ('dir /b .') DO somecommand %%f

Solution 2:

In DOS you couldn't use environment variables on the command line, only in batch files, where they used the % sign as a delimiter. If you wanted a literal % sign in a batch file, e.g. in an echo statement, you needed to double it.

This carried over to Windows NT which allowed environment variables on the command line, however for backwards compatibility you still need to double your % signs in a .cmd file.