113

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.

Tyler
  • 1,440
  • 2
  • 11
  • 11

2 Answers2

181

(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
marapet
  • 54,856
  • 12
  • 170
  • 184
  • 24
    Is there an explanation for why I can get away with using just one percent sign in a FOR loop, when executed directly from a command prompt, and not from a batch file? I know about the DOS heritage, but we **can** use variables from a command line now. – Alec Mev Oct 29 '13 at 11:58
  • 7
    Also, make sure the variable is a single character. – jiggunjer Sep 02 '16 at 02:22
  • 1
    What if I want to issue command which has % in it e.g.: for /f %%i in ('git log -1 --pretty=format:"%%H"') do set GIT_COMMIT=%%i – Wakan Tanka Jan 25 '19 at 11:45
  • In addition to %G in a for loop, %1 is also allowed. %% is needed in a script to avoid ambiguities. "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 %." See [details](https://ss64.com/nt/syntax-percent.html). – dosentmatter Feb 27 '21 at 06:12
20

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.

Neil
  • 54,642
  • 8
  • 60
  • 72
  • 1
    Thank you! Your answer is very understandable. `%%` in batch acted like `\\ ` in bash. Where one would need to cancel the meaning of the previous percent-sign in a batch file; because variables in batch look like `%var%`. So because percent had a special meaning you needed to use `%%var%%` so a variable was still usable in a batch file. – Whitequill Riclo Dec 01 '21 at 04:59