How a command line is interpreted
suggest changeThe parsing of a command line into a sequence of commands is complex, and varies subtly from command interpreter to command interpreter. There are, however, four main components:
Variable substitution
A command line is scanned for variable specifications, and any found are replaced with the contents of those variables.
Quoting
`Special characters can be quoted, to remove their special meanings.
Syntax
Command lines are developed into a sequence of commands according to a syntax.
Redirection
Redirection specifications are applied, and removed from the command line, before an individual command in a sequence is executed.
Variable substitution
Command lines can contain variable specifications. These comprise a %
character followed by a name, followed by a second %
character unless the name is a digit in 0 ... 9 or an asterisk *.
Variable specifications are replaced with values as follows:
%%
, such as%PATH%
or%USERNAME%
, is replaced with the value of the named environment variable. For example,%PATH%
is replaced by the value of the PATH environment variable.varname
%
for 0 <= n <= 9, such as%0
or%9
, is replaced with the value of the n-th parameter passed to the batch file when it was invoked, subject to any subsequent modifications by the SHIFT command. For example:%2
is replaced by the value of the second batch file parameter.n
- %* is replaced with the values of all the command-line parameters except for %0, even those beyond index 9. SHIFT command has no impact on the result of %*. See also command-line arguments.
Special names
Some variable names are not visible using SET command. Rather, they are made available for reading using the %
notation. To find out about them, type help set
.
Special variable names and what they expand to:
Name | Replacement Value Used |
---|---|
%CD% | The current directory, not ending in a slash character if it is not the root directory of the current drive |
%TIME% | The system time in HH:MM:SS.mm format. |
%DATE% | The system date in a format specific to localization. |
%RANDOM% | A generated pseudo-random number between 0 and 32767. |
%ERRORLEVEL% | The error level returned by the last executed command, or by the last called batch script. |
%CMDEXTVERSION% | The version number of the Command Processor Extensions currently used by cmd.exe. |
%CMDCMDLINE% | The content of the command line used when the current cmd.exe was started. |
Links:
Quoting and escaping
You can prevent the special characters that control command syntax from having their special meanings as follows, except for the percent sign (%
):
- You can surround a string containing a special character by quotation marks.
- You can place caret (
^
), an escape character, immediately before the special characters. In a command located after a pipe (|
), you need to use three carets (^^^
) for this to work.
The special characters that need quoting or escaping are usually <
, >
, |
, &
, and ^
. In some circumstances, !
and \
may need to be escaped. A newline can be escaped using caret as well.
When you surround the string using quotation marks, they become part of the argument passed to the command invoked. By contrast, when you use caret as an escape character, the caret does not become part of the argument passed.
The percent sign (%
) is a special case. On the command line, it does not need quoting or escaping unless two of them are used to indicate a variable, such as %OS%
. But in a batch file, you have to use a double percent sign (%%
) to yield a single percent sign (%
). Enclosing the percent sign in quotation marks or preceding it with caret does not work.
Examples
echo "Johnson & son"
Echoes the complete string rather than splitting the command line at the & character. Quotes are echoed as well
echo Johnson ^& son
As above, but using caret before the special character ampersand. No quotes are echoed.
echo Johnson & son
Does not use an escape character and therefore, "son" is interpreted as a separate command, usually leading to an error message that command son is not found.
echo A ^^ B
Echoes
A ^ B
. Caret needs escaping as well or else it is interpreted as escaping a space.echo > NUL | echo A ^^^^ B
Echoes
A ^ B
. When after a pipe, a caret used for escaping needs to be tripled to work; the fourth caret is the one being escaped.if 1 equ 1 ^echo Equal &^echo Indeed, equal
Echoes the two strings. The caret at the end of the line escapes the newlines, leading to the three lines being treated as if they were a single line. The space before the first caret is necessary or else 1 gets joined with the following echo to yield
1echo
.attrib File^ 1.txt
Does not show attributes of file named File
1.txt
since escaping of space does not work. Using quotes, as inattrib "File 1.txt"
, works.echo The ratio was 47%.
If run from a batch, the percent sign is ignored.
echo The ratio was 47%%.
If run from a batch, the percent sign is output once.
set /a modulo=14%%3
If run from a batch, sets modulo variable to 2, the remainder of dividing 14 by 3. Does not work with single
%
.for %%i in (1,2,3) do echo %%i
If run from a batch, outputs 1, 2 and 3.
echo %temp%
Outputs the content of temp variable even if run from a batch file. Use of the percent sign in a batch to access environment variables and passed arguments needs no escaping.
echo ^%temp^%
Outputs literally %temp% when run from the command line.
echo %%temp%%
Outputs literally
%temp%
when run from a batch.echo //comment line | findstr \//
- Command FINDSTR uses backslash (
\
) for escaping. Unlike caret, this is internal to the command and unknown to the command shell.
- Command FINDSTR uses backslash (
Links:
- Syntax : Escape Characters, Delimiters and Quotes at ss64
- Command shell overview at Microsoft
- set at Microsoft
Syntax
Command lines are developed into a sequence of commands according to a syntax. In that syntax, simple commandsmay be combined to form pipelines, which may in turn be combined to form compound commands, which finally may be turned into parenthesized commands.
A simple command is just a command name, a command tail, and some redirection specifications. An example of a simple command is dir *.txt > somefile
.
A pipeline is several simple commands joined together with the "pipe" metacharacter — |
, also known as the "vertical bar". The standard output of the simple command preceding each vertical bar is connected to the standard input of the simple command following it, via a pipe. The command interpreter runs all of the simple commands in the pipeline in parallel. An example of a pipeline (comprising two simple commands) is dir *.txt | more
.
A compound command is a set of pipelines separated by conjunctions. The pipelines are executed sequentially, one after the other, and the conjunction controls whether the command interpreter executes the next pipeline or not. An example of a compound command (comprising two pipelines, which themselves are just simple commands) is move file.txt file.bak && dir > file.txt
.
The conjunctions:
&
- An unconditional conjunction. The next pipeline is always executed after the current one has completed executing.&&
- A positive conditional conjunction. The next pipeline is executed if the current one completes executing with a zero exit status.||
- A negative conditional conjunction. The next pipeline is executed if the current one completes executing with a non-zero exit status.
A parenthesized command is a compound command enclosed in parentheses (i.e. ( and )). From the point of view of syntax, this turns a compound command into a simple command, whose overall output can be redirected.
For example: The command line ( pushd temp & dir & popd ) > somefile.txt
causes the standard output of the entire compound command ( pushd temp & dir & popd )
to be redirected to somefile.txt
.
Links:
- Conditional Execution at ss64.com
- Using parenthesis/brackets to group expressions at ss64.com
- Command shell overview at Microsoft
Redirection
Redirection specifications are applied, and removed from the command line, before an individual command in a sequence is executed. Redirection specifications control where the standard input, standard output, and standard error file handles for a simple command point. They override any effects to those file handles that may have resulted from pipelining. (See the preceding section on command syntax.) Redirection signs >
and >>
can be prefixed with 1 for the standard output (same as no prefix) or 2 for the standard error.
The redirection specifications are:
< filename Redirect standard input to read from the named file.
> filename Redirect standard output to write to the named file, overwriting its previous contents.
>> filename Redirect standard output to write to the named file, appending to the end of its previous contents.
>&h Redirect to handle h, where handle is any of 0—standard input, 1—standard output, 2—standard error, and more.
<&h Redirect from handle h.
Examples:
dir *.txt >listing.log
Redirects the output of the
dir
command to listing.log file.dir *.txt > listing.log
As above; the space before the file name makes no difference. However, if you type this into the command window, auto-completion with tab after typing
> l
actually works, while it does not work with>listing.log
.dir *.txt 2>NUL
Redirects errors of the
dir
command to nowhere.dir *.txt >>listing.log
Redirects the output of the
dir
command to listing.log file, appending to the file. Thereby, the content of the file before the redirected command was executed does not get lost.dir *.txt >listing.log 2>&1
Redirects the output of the
dir
command to listing.log file, along with the error messages.dir *.txt >listing.log 2>listing-errors.log
Redirects the output of the
dir
command to listing.log file, and the error messages to listing-errors.log file.>myfile.txt echo Hello
The redirection can precede the command.
echo Hello & echo World >myfile.txt
Only the 2nd
echo
gets redirected.(echo Hello & echo World) >myfile.txt
Output of both echos gets redirected.
type con >myfile.txt
Redirects console input (con) to the file. Thus, allows multi-line user input terminated by user pressing Control + Z. See also user input.
(for %i in (1,2,3) do @echo %i) > myfile.txt
Redirects the entire output of the loop to the file.
for %i in (1,2,3) do @echo %i > myfile.txt
Starts redirection anew each time the body of the loop is entered, losing the output of all but the latest loop iteration.
Links: