For example, this:
ffmpeg -i %1 -c:v libx264 -preset medium -crf 30 -c:a aac "%~n1_OUT.mp4"
Does not need %%1 and %%~n1 respectively.
But this:
FOR /f %%f in ('dir /b .') DO somecommand %%f
Needs %%, otherwise it's not working.
Can somebody explain any logical reason for this chaotic design?
CodePudding user response:
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 variableVAR
is not set. - There is no escaping of
%
-signs supported, so%%VAR%%
results in%
value ofVAR
%
.
- 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%
.
- Batch files may have arguments, which are expanded by argument references like
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 lead 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