MustWatch
Introduction
This book describes Windows scripting as implemented bycmd.exe
command interpreter. This book first describes using the Windows NT command interpreter, how it receives, parses, and processes commands from users. Then it describes various commands available. To obtain an extensive list of Windows commands and their short summaries, open the command prompt on any Windows computer, and type help. To find out about a particular command, type the name of the command followed by/?
. The subject of this book is also known as "batch programming", even though "batch" refers not only to batch files for MS DOS and Windows command interpreter. Other subject terms include "batch file programming", "batch file scripting", "Windows batch command", "Windows batch file", "Windows command line", "Windows command prompt", and "Windows shell scripting".How a command line is interpreted
The 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, typehelp 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. |
%
):
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 in attrib "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.
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
.
>
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.
echo A
to echo B
in the batch shortly after starting it, the output will be B
.
@echo off
ping -n 6 127.0.0.1 >nul & REM wait
echo A
What is on a single line does matter; changing echo A
in the following batch after running it has no impact:
@echo off
ping -n 6 127.0.0.1 >nul & echo A
Nor have after-start changes have any impact on commands bracketed with ( and ).
Thus, changing echo A
after starting the following batch has no impact:
@echo off
for /L %%i in (1,1,10) do (
ping -n 2 127.0.0.1 >nul & REM wait
echo A
)
Same happens for any other enclosing, including:
@echo off
(
ping -n 6 127.0.0.1 >nul & REM wait
echo A
)
set myvar=
.
The command interpreter inherits its initial set of environment variables from the process that created it.
In the case of command interpreters invoked from desktop shortcuts this will be Windows Explorer, for example.
Command interpreters generally have textual user interfaces, not graphical ones, and so do not recognize the Windows message that informs applications that the environment variable template in the Registry has been changed.
Changing the environment variables in Control Panel will cause Windows Explorer to update its own environment variables from the template in the Registry, and thus change the environment variables that any subsequently invoked command interpreters will inherit.
However, it will not cause command interpreters that are already running to update their environment variables from the template in the Registry.
COMSPEC
environment variable contains the full path name of the command interpreter program file.
This is just inherited from the parent process, and is thus indirectly derived from the setting of COMSPEC
in the environment variable template in the Registry.
PATH
environment variable comprises a list of directory names, separated by semi-colon characters.
This is the list of directories that are searched, in order, when locating the program file of an external command to execute.
PATHEXT
environment variable comprises a list of filename extensions, separated by semi-colon characters.
This is the list of filename extensions that are applied, in order, when locating the program file of an external command to execute.
An example content of PATHEXT
printed by echo %PATHEXT%
:
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
By adding ".PL" to the variable, you can ensure Perl programs get run from the command line even when typed without the ".pl" extension.
Thus, instead of typing "mydiff.pl a.txt b.txt", you can type "mydiff a.txt b.txt".
Adding ".PL" to the variable in Windows Vista and later:
setx PATHEXT %PATHEXT%;.PL
If you use "set" available in Windows XP, the effect will be temporary and impacting only the current console or process.
Links:
PROMPT
environment variable controls the text emitted when the command interpreter displays the prompt.
The command interpreter displays the prompt when prompting for a new command line in interactive mode, or when echoing a batch file line in batch file mode.
Various special character sequences in the value of the PROMPT
environment variable cause various special effects when the prompt is displayed, as in the following table:
Characters | Expansion Result |
---|---|
$$ | $ character itself |
$A | & symbol AKA ampersand. A convenience, since it is difficult to place a literal & in the value of the PROMPT environment variable using the SET command. |
$B | Vertical bar '|' (pipe symbol) |
$C | Left parenthesis '(' |
$D | Current date |
$E | ESC (ASCII code 27) |
$F | Right parenthesis ')' |
$G | Greater-than symbol '>' |
$H | Backspace (deletes previous character) |
$L | Less-than symbol '<' |
$M | Remote name linked to the current drive if it is a network drive; empty string otherwise. |
$N | Current drive letter |
$P | Current drive letter and full path |
$Q | '=' (equals sign) |
$S | ' ' (space character) |
$T | Current system time |
$V | Windows version number |
$_ | <CR> (carriage return character, aka "enter") |
$+ | As many plus signs (+) as there are items on the pushd directory stack |
/
) rather than, as in some other operating systems, with a minus sign (-
).
Switches are case-insensitive rather than, as in some other operating systems, case-sensitive.
If a command from another operating system is ported to Windows (such as grep
), it usually retains the option conventions from the original operating system, including the use of minus sign and case-sensitivity.
Examples:
dir /?
Displays the help.
This option is provided by many commands.
dir /b /s
Lists all files and folders in the current folder recursively.
Two switches are used: /b
and /s
.
dir /bs
Does not work; switches cannot be accumulated behind a single slash.
findstr /ric:"id: *[0-9]*" File.txt
Unlike many other commands, findstr
allows the accumulation of switches behind a single slash.
Indeed, r, i and c are single-letter switches.
dir/b/s
Works.
In dir
, removing whitespace between the command and the first switch or between the switches does not make a difference; thus, does the same as dir /b /s
.
tree/f/a
Does not work, unlike tree /f /a
.
In tree, separation by whitespace is mandatory.
Nor does find/i/v work.
dir /od
The switch letter o is further modified by a single letter specifying that ordering should be by date.
The letter d is not a switch by itself.
Similar cases include dir /ad
and more /t4
.
dir /B /S
The switches are case-insensitive, unlike in some other operating systems.
sort /r file.txt
Sorts the file in a reverse order.
sort /reverse file.txt
Sort allows the switch string to be longer than a single-letter.
sort /reve file.txt
Sort allows the specified switch string to be a sub-string of the complete long name of the switch.
Thus, does the same as the above.
sort /reva file.txt
Does not work, since reva
is not a sub-string of reverse
.
taskkill /im AcroRd32.exe
Taskkill
requires a multi-letter switch name for /im
; shortening to /i
does not work.
java -version
Java, which originated in the environment of another operating system family, uses the minus convention for its switches AKA options.
grep --help
If GNU grep is installed, it requires multi-letter switches to be preceded by two dashes.
&&
and ||
; see also syntax.
It can be tested using IF.
The value can be accessed from ERRORLEVEL
variable.
Examples:
dir >NUL && echo Success
The part after && is executed only if the error level is zero.
color 00 || echo Failure
The part after || is executed only if the error level is non-zero, whether positive or negative.
color 00 || ( echo Failure)
Multi-line bracketing works as well.
echo %ERRORLEVEL%
Displays the error level without changing it.
if %errorlevel% equ 0 echo The error level is zero, meaning success.
if %errorlevel% neq 0 echo The error level is non-zero, meaning failure.
if errorlevel 1 echo The error level is >= 1, meaning failure via positive error level.
Does not cover failure via negative error level.
Note the >=
part: this is not the same as if %errorlevel% equ 1
.
exit /b 1
Returns a batch file, setting the error level to 1.
cmd /c "exit /b 10"
In the middle of a batch file or on the command line, sets the error level to 10.
(cmd /c "exit /b 0" && Echo Success) & (cmd /c "exit /b -1" || Echo Failure)
As above, showing the error level is indeed affected.
(cmd /c "exit /b 0" & cmd /c "exit /b 1") || Echo Failure
The error level of a chain created by &
is the error level of the last command of the chain.
cmd /c "exit /b -1" & if not errorlevel 1 echo Would-be success
The if not errorlevel 1
test, which might appear to test for success, passes on negative numbers: it tests on "not error level >= 1", which is "error level <= 0".
set myerrorlevel=%errorlevel%
Remembers the error level for later.
set errorlevel=0
To be avoided: overshadows the built-in errorlevel
variable.
Ensures that subsequent accesses via %ERRORLEVEL%
return 0 rather than the actual error level.
cmd /c "exit /b 0"if 1 equ 1 ( cmd /c "exit /b 1" & echo %errorlevel% )
Displays 0, since %errorlevel%
gets expanded before cmd /c "exit /b 1"
gets executed.
if not "%a:bc=%"=="%a%" echo yes
If variable a contains "bc" as a substring, echo "yes".
This test is a trick that uses string replacement, discussed below.
This test does not work if the variable contains a quotation mark.
Testing for "starts with":
if %a:~0,1%==a echo yes & rem If variable a starts with "a", echo "yes".
if %a:~0,2%==ab echo yes & rem If variable a starts with "ab", echo "yes".
String replacement:
set a=abcd & echo %a:c=% & rem replace c with nothing; result: abd
set a=abcd & echo %a:c=e% & rem replace c with e; result: abed;
set a=abcd & echo %a:*c=% & rem replace all up to c with nothing; result: d
rem Above, the asterisk (*) only works at the beginning of the sought pattern.
See also the help for SET command: set /?.
Splitting a string by any of " ", ",", and ";": ["space", "comma" and "semicolon":]
set myvar=a b,c;d
for %%a in (%myvar%) do echo %%a
Splitting a string by semicolon, assuming the string contains no quotation marks:
@echo off
set myvar=a b;c;d
set strippedvar=%myvar%
:repeat
for /f "delims=;" %%a in ("%strippedvar%") do echo %%a
set prestrippedvar=%strippedvar%
set strippedvar=%strippedvar:*;=%
if not "%prestrippedvar:;=%"=="%prestrippedvar%" goto :repeat
Limitations:
The above string processing does not work with parameter variables (%1
, %2
, ...).
%1
, %2
, ..., %9
.
There can be more than nine arguments; to access them, see how to loop over all of them below.
The syntax %0
does not refer to a command-line argument but rather to the name of the batch file.
Testing for whether the first command-line argument has been provided:
if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b
A robust looping over all command-line arguments using SHIFT
(for each command-line argument, ...):
:argactionstart
if -%1-==-- goto argactionend
echo %1 & REM Or do any other thing with the argument
shift
goto argactionstart
:argactionend
A robust looping over all command-line arguments using SHIFT
without modifying %1
, %2
, etc.:
call :argactionstart %*
echo Arg one: %1 & REM %1, %2, etc.
are unmodified in this location
exit /b
:argactionstart
if -%1-==-- goto argactionend
echo %1 & REM Or do any other thing with the argument
shift
goto argactionstart
:argactionend
exit /b
Transferring command-line arguments to environment variables:
setlocal EnableDelayedExpansion
REM Prevent affecting possible callers of the batch
REM Without delayed expansion, !arg%argno%! used below won't work.
set argcount=0
:argactionstart
if -%1-==-- goto argactionend
set /a argcount+=1
set arg%argcount%=%1
shift
goto argactionstart
:argactionend
set argno=0
:loopstart
set /a argno+=1
if %argno% gtr %argcount% goto loopend
echo !arg%argno%! & REM Or do any other thing with the argument
goto loopstart
:loopend
Looping over all command-line arguments, albeit not a robust one:
for %%i in (%*) do (
echo %%i
)
This looks elegant but is non-robust, maltreating arguments containing wildcards (*
, ?
).
In particular, the above for command replaces arguments that contain wildcards (*
, ?
) with file names that match them, or drops them if no files match.
Nonetheless, the above loop works as expected as long as the passed arguments do not contain wildcards.
Finding the number of command-line arguments, in a non-robust way:
set argcount=0
for %%i in (%*) do set /a argcount+=1
Again, this does not work with arguments containing wildcards.
The maximum possible number of arguments is greater than 4000, as empirically determined on a Windows Vista machine.
The number can differ on Windows XP and Windows 7.
In passing arguments to a batch script, characters used for argument separation are the following ones:
space
comma
semicolon
equal sign
tab character
Thus, the following lines pass the same four arguments:
test.bat a b c d
test.bat a,b,c,d
test.bat a, b, c, d
test.bat a;b;c;d
test.bat a=b=c=d
test.bat a b,c;,;=d
Yes, even the line with a b,c;,;=d
passes four arguments, since a sequence of separating characters is considered a single separator.
To have a space, comma or semicolon in the argument value, you can pass the value enclosed in quotation marks.
However, the quotation marks become part of the argument value.
To get rid of the enclosing quotation marks when referring to the argument in the script, you can use %~<number>
described in percent tilde.
When passing arguments to an invoked command rather than a batch script, you usually need to separate the command from the first argument using a space.
However, for internal commands, that separation is not necessary if the first character after the command name is one of a couple of symbols, including .\/
, and more:
echo.
Outputs a newline.
tree.
Fails: "tree." not found.
tree is an external command.
dir..
Lists the content of the parent directory.
cd..
Changes the current directory to the parent one.
cd\
Changes the current directory to the root one.
start.
Opens Windows Explorer from the current directory.
dir/b/s
Lists directory content recursively, showing full paths.
*
: any sequence of characters
?
: a single character other than a period (.
) or, if part of a sequence of question marks at the end of a maximum period-free part of a file name, possibly zero number of characters; see examples for clarification
Examples:
dir *.txt
Matches Myfile.txt
, Plan.txt
and any other file with the .txt
extension.
dir *txt
The period does not need to be included.
However, this will also match files named without the period convention, such as myfiletxt
.
ren *.cxx *.cpp
Renames all files with .cxx
extension to have .cpp
extension.
dir a?b.txt
Matches files aab.txt
, abb.txt
, a0b.txt
, etc.
Does not match ab.txt
, since a question mark followed by a character other than a question mark or period cannot match zero characters.
Does not match a.b.txt
, since a question mark cannot match a period.
dir ???.txt
Matches .txt
, a.txt
, aa.txt
, and aaa.txt
, among others, since each question mark in the sequence followed by a period can match zero number of characters.
dir a???.b???.txt???
Matches a.b.txt
, among others.
While the last question mark sequence is not followed by a period, it is still a sequence at the end of a maximum period-free part of a file name.
dir ????????.txt & @REM eight question marks
Matches the same files as *.txt
, since each file also has a short file name that has no more than 8 characters before .txt
.
Quirk with short file names: the wildcard matching is performed both on long file names and the usually hidden short 8 chars + period + 3 chars file names.
This can lead to bad surprises.
Unlike shells of some other operating systems, the cmd.exe
shell does not perform wildcard expansion (replacement of the pattern containing wildcards with the list of file names matching the pattern) on its own.
It is the responsibility of each program to treat wildcards as such.
This enables such things as ren *.txt *.bat
, since the ren
command actually sees the *
wildcard rather than a list of files matching the wildcard.
Thus, echo *.txt
does not display files in the current folder matching the pattern but rather literally displays *.txt
.
Another consequence is that you can write findstr a.*txt
without fearing that the a.*txt
part gets replaced with the names of some files in the current folder.
Furthermore, recursive findstr /s pattern *.txt
is possible, while in some other operating systems, the *.txt
part would get replaced with the file names found in the current folder, disregarding nested folders.
Commands accepting wildcards include ATTRIB, COPY, DIR, FINDSTR, FOR, REN, etc.
SET
/P
command
CHOICE command
Using type con >myfile.txt
, for which the multi-line user input is terminated by user pressing Control + Z.
%1
:
Syntax | Expansion Result | Example |
---|---|---|
%~1 | %1 with no enclosing quotation marks | Not provided |
%~f1 | Full path with a drive letter | C:\Windows\System32\notepad.exe |
%~d1 | Drive letter | C: |
%~p1 | Drive-less path with the trailing backslash | \Windows\System32\ |
%~n1 | For a file, the file name without path and extensionFor a folder, the folder name | notepad |
%~x1 | File name extension including the period | .exe |
%~s1 | Modify of f, n and x to use short name | Not provided |
%~a1 | File attributes | --a------ |
%~t1 | Date and time of last modification of the file | 02.11.2006 11:45 |
%~z1 | File size | 151040 |
%~pn1 | A combination of p and n | \Windows\System32\notepad |
%~dpnx1 | A combination of several letters | C:\Windows\System32\notepad.exe |
%~$PATH:1 | The full path of the first match found in the folders present in the PATH variable, or an empty string in no match. | |
%~n0 | %~n applied to %0:The extensionless name of the batch | tildetest |
%~nx0 | %~nx applied to %0:The name of the batch | tildetest.bat |
%~d0 | %~f applied to %0:The drive letter of the batch | C: |
%~dp0 | %~dp applied to %0:The folder of the batch with trailing backslash | C:\Users\Joe Hoe\ |
%%i
.
exit /b
is used instead of goto :eof
to the same effect.
Also, remember that the equal sign is a way to separate parameters.
Thus, the following items achieve the same:
call :sayhello result=world
call :sayhello result world
call :sayhello result,world
call :sayhello result;world
(See command-line arguments as a reminder)
set /a num=-2147483647-1
.
The syntax is reminiscent of the C language.
Arithmetic operators include *, /, % (modulo), +, -.
In a batch, modulo has to be entered as "%%".
Bitwise operators interpret the number as a sequence of 32 binary digits.
These are ~ (complement), & (and), | (or), ^ (xor), << (left shift), >> (right shift).
A logical operator of negation is !: it turns zero into one and non-zero into zero.
A combination operator is ,: it allows more calculations in one set command.
Combined assignment operators are modeled on "+=", which, in "a+=b", means "a=a+b".
Thus, "a-=b" means "a=a-b".
Similarly for *=, /=, %=, &=, ^=, |=, <<=, and >>=.
The precedence order of supported operators, is as follows:
( )
* / % + -
<< >>
&
^
|
= *= /= %= += -= &= ^= |= <<= >>=
,
set /a num="255^127"
set /a "num=255^127"
Alternative placement of quotation marks.
set /a num=255^^127
Escape ^ using ^ instead of quotation marks.
Examples:
set n1=40 & set n2=25
set /a n3=%n1%+%n2%
Uses the standard percent notation for variable expansion.
set n1=40 & set n2=25
set /a n3=n1+n2
Avoids the percent notation around variable names as unneeded for /a.
set /a num="255^127"
Encloses "^" in quotation marks to prevent its special meaning for the command interpreter.
set /a n1 = (10 + 5)/5
The spaces around = do not matter with /a.
However, getting used to it lends itself to writing "set var = value" without /a, which sets the value of "var " rather than "var".
if 1==1 (set /a n1=(2+4)*5)
Does not work: the arithmetic brackets within grouping brackets cause trouble.
if 1==1 (set /a n1=^(2+4^)*5)
Escaping the arithmetic brackets with caret (^) works, as does enclosing "n1=2+(4*5)" in quotation marks.
set /a n1=2+3,n2=4*7
Performs two calculations.
set /a n1=n2=2
Has the same effect as n1=2,n2=2.
set n1=40 & set n2=25 & set /a n3=n1+n2
Works as expected.
set /a n1=2,n2=3,n3=n1+n2
Works as expected.
set n1=40 & set n2=25 & set /a n3=%n1%+%n2%
Does not work unless n1 and n2 were set previously.
The variable specifications %n1%" and "%n2"% get expanded the first set command is executed.
Dropping percent notation makes it work.before
set /a n1=2,n2=3,n3=%n1%+%n2%
Does not work unless n1 and n2 were set previously, for the reason stated in the previous example.
set /a n1=0xffff
Sets n1 using hexadecimal notation.
set /a n1=0777
Sets n1 using octal notation.
set /a n1=%random%
A pseudo-random number from 0 to 32767 = 2^15-1.
set /a n1="%random%>>10"
A pseudo-random number from 0 to 31 = 2^5-1.
The shift right operator drops 10 out of 15 bits, keeping 5 bits.
set /a n1=%random%%50
A pseudo-random number from 0 to 49.
Uses the % modulo operator.
In a batch, %% is needed for modulo: set /a n1=%random%%%50
.
Because of this particular use of the modulo, the result is not perfectly uniform; it is uniform if the 2nd modulo operand--above 50--equals to a power of 2, e.g.
256 = 2^8.
set /a n1="(%random%<<15)+%random%"
A pseudo-random number from 0 to 1073741823 = 2^30 - 1.
Combines the two 15-bit random numbers produced by %random% alone to produce a single 30-bit random number..
set /a n1="((%random%<<15)+%random%)%1000000"
As above, but again using modulo, this time to achieve the range 0 to 999999.
An example calculation that prints prime numbers:
@echo off
setlocal
set n=1
:print_primes_loop
set /a n=n+1
set cand_divisor=1
:print_primes_loop2
set /a cand_divisor=cand_divisor+1
set /a cand_divisor_squared=cand_divisor*cand_divisor
if %cand_divisor_squared% gtr %n% echo Prime %n% & goto :print_primes_loop
set /a modulo=n%%cand_divisor
if %modulo% equ 0 goto :print_primes_loop & REM Not a prime
goto :print_primes_loop2
dir /b /s *base*.doc*
Outputs all files in the current folder and its sub-folders such that the file name before the extension contains the word base
and whose extension starts with doc
, which includes doc
and docx
.
The files are output with full paths, one file per line.
dir /b /s *.txt | findstr /i pers.*doc
Combines the result of outputting files including their complete paths with the findstr
filtering command supporting limited regular expressions, yielding a versatile and powerful combination for finding files by names and the names of their directories.
for /r %i in (*) do @if %~zi geq 1000000 echo %~zi %i
For each file in the current folder and its sub-folders that has the size greater than or equal to 1,000,000 bytes, outputs the file size in bytes and the full path of the file.
For the syntax in %~zi
, see percent tilde.
forfiles /s /d 06/10/2015 /c "cmd /c echo @fdate @path"
For each file in the current folder and its sub-folders modified on 10 June 2015 or later, outputs the file modification date and full file path.
The date format after /d
is locale specific.
Thus, allows to find most recently modified files.
(for /r %i in (*) do @echo %~ti :: %i) | findstr 2015.*::
Searching the current folder recursively, outputs files whose last modification date is in year 2015.
Places the modification date and time, followed by a double colon, before the file name.
Works as long as the used version of Windows and locale displays dates in a format that contains four-digit years.
The double colon is used to make sure the findstr
command is matching the date and not the file name.
for /r %i in (*) do @echo %~ti | findstr 2015 >NUL && echo %i
As above, outputs files changed in 2015.
Unlike the above, only outputs the files, not the modification dates.
findstr /i /s /m cat.*mat *.txt
Finds files by their content.
Performs a full text search for regular expression cat.*mat in files with names ending in .txt
, and outputs the files names.
The /m
switch ensures only the file names are output.
where *.bat
Outputs all .bat files in the current directory and in the directories that are in PATH
.
cmd.exe
after pressing Windows + R
, you can use multiple keyboard shortcuts, including function keys:
Tab
: Completes the relevant part of the typed string from file names or folder names in the current folder.
The relevant part is usually the last space-free part, but use of quotation marks changes that.
Generally considers both files and folders for completion, but cd
command only considers folders.
Up and down arrow keys: Enters commands from the command history, one at a time.
Escape
: Erases the current command line being typed.
F1
: Types the characters from the single previously entered command from the command history, one character at a time.
Each subsequent press of F1
enters one more character.
F2
: Asks you to type a character, and enters the shortest prefix of the previous command from the command history that does not include the typed character.
Thus, if the previous command was echo Hello world and you typed o, enters ech.
F3
: Enters the single previous command from the command history.
Repeated pressing has no further effect.
F4
: Asks you to type a character, and erases the part of the currently typed string that starts at the current cursor location, continues to the right, and ends with the character you entered excluding that character.
Thus, if you type echo Hello world, place the cursor at H using left arrow key, press F4 and then w, you get echo world.
F5
: Enters previous commands from the command history, one at a time.
F6
: Enters Control+Z character.
F7
: Opens a character-based popup window with the command history, and lets you use arrow key and enter to select a command.
After you press enter in the popup, the command is immediately executed.
F8
: Given an already typed string, shows items from the command history that have that string as a prefix, one at a time.
F9
: Lets you enter the number of the command from the command history, and then executes the command.
Alt + F7
: Erases the command history.
The above are also known as command prompt keyboard shortcuts.
The availability of the above shortcuts does not seem to depend on running DOSKEY.
:
), the use of backslash (\
) as the path separator, and the distinction between relative and absolute paths.
Forward slash (/
) often works when used instead of (\
) but not always; it is normally used to mark switches (options).
Using forward slash can lead to various obscure behaviors, and is best avoided.
Special device names include NUL
, CON
, PRN
, AUX
, COM1
, ..., COM9
, LPT1
, ..., LPT9
; these can be redirected to.
Examples:
attrib C:\Windows\System32\notepad.exe
Succeeds if the file exists, as it should.
This is an absolute path with a drive letter.
It is also known as a fully qualified path.
attrib \Windows\System32\notepad.exe
Succeeds if the current drive is C:
, and if the file exists, as it should.
This is an absolute path without a drive letter.
cd /d C:\Windows & attrib System32\notepad.exe
Succeeds if the file exists.
The path given to attrib
is a relative path.
cd /d C:\Windows\System32 & attrib C:notepad.exe
Succeeds if the file exists.
The path given to attrib
is a one despite containing a drive letter: there would have to be C:\notepad.exe
with a backslash for that to be an absolute path.relative
cd /d C:\Windows & attrib .\System32\notepad.exe
Succeeds if the file exists.
A single period denotes the current folder.
attrib .
A single period denotes the current folder.
cd /d C:\Windows & attrib .\System32\\\notepad.exe
Succeeds if the file exists.
Piling of backslashes has no impact beyond the first backslash.
cd /d C:\Windows & attrib .\System32
Succeeds if the folder exists.
cd /d C:\Windows & attrib .\System32\
Fails.
Folders are usually denoted without the final backslash.
cd C:\Windows\System32\
Succeeds.
cd ..
A double period denotes the parent folder.
attrib C:\Windows\System32\..\..\Windows\System32
A double period can be used in the middle of the path to navigate to the parent folder, even multiple times.
attrib \\myserver\myvolume
A network UNC path starts with double backslash and no drive letter.
cd \\myserver\myvolume
Does not work; changing to a server folder in this direct manner does not work.
pushd \\myserver\folder
Automatically creates a drive for the folder and changes to it.
After you use POPD, the drive gets unassigned again.
attrib C:/Windows/System32/notepad.exe
Succeeds on multiple versions of cmd.exe
.
Uses forward slashes.
%
and !
to indicate variables.
There, %i%
is the value of variable i
with the immediate expansion while !i!
is the value of variable i
in the delayed expansion.
@echo off
setlocal EnableDelayedExpansion
for /l %%i in (1, 1, 10) do (
set array_%%i=!random!
)
for /l %%i in (1, 1, 10) do (
echo !array_%%i!
)
:: For each item in the array, not knowing the length
set i=1
:startloop
if not defined array_%i% goto endloop
set array_%i%=!array_%i%!_dummy_suffix
echo A%i%: !array_%i%!
set /a i+=1
goto startloop
:endloop
echo "abcbbc"| perl -pe "s/a.*?c/ac/"
Lets Perl act as sed, the utility that supports textual replacements specified using regular expressions.
echo a b| perl -lane "print $F[1]"
Lets Perl act as cut command, displaying the 2nd field or column of the line, in this case b.
Use $F[2]
to display 3rd field; indexing starts at zero.
Native solution: FOR
/f
.
perl -ne "print if /\x22hello\x22/" file.txt
Acts as grep or FINDSTR, outputting the lines in file.txt
that match the regular expression after if.
Uses the powerful Perl regular expressions, more powerful than those of FINDSTR.
perl -ne "$.
<= 10 and print" MyFile.txt
Lets Perl act as head -10 command, outputting the first 10 lines of the file.
perl -e "sleep 5"
Waits for 5 seconds.
for /f %i in ('perl -MPOSIX -le "print strftime '%Y-%m-%d', localtime"') do @set isodate=%i
Gets current date in the ISO format into isodate
variable.
perl -MWin32::Clipboard -e "print Win32::Clipboard->Get()"
Outputs the text content of the clipboard.
When stored to getclip.bat, yields a handy getclip command to complement CLIP command.
perl -MText::Diff -e "print diff 'File1.txt', 'File2.txt'"
Outputs differences between two files in a format similar to diff command known from other operating systems, including context lines, lines starting with + and lines starting with -.
On the web, Perl one-liners are often posted in the command-line conventions of another operating system, including the use of apostrophe ('
) to surround the arguments instead of Windows quotation marks.
These need to be tweaked for Windows.
copy /b file.txt+,,
Command | Description |
---|---|
ASSOC | Associates an extension with a file type (FTYPE). |
BREAK | Sets or clears extended CTRL+C checking. |
CALL | Calls one batch program from another. |
CD, CHDIR | Displays or sets the current directory. |
CHCP | Displays or sets the active code page number. |
CLS | Clears the screen. |
COLOR | Sets the console foreground and background colors. |
COPY | Copies files. |
DATE | Displays and sets the system date. |
DEL, ERASE | Deletes one or more files. |
DIR | Displays a list of files and subdirectories in a directory. |
ECHO | Displays messages, or turns command echoing on or off. |
ELSE | Performs conditional processing in batch programs when "IF" is not true. |
ENDLOCAL | Ends localization of environment changes in a batch file. |
EXIT | Quits the CMD.EXE program (command interpreter). |
FOR | Runs a specified command for each file in a set of files. |
FTYPE | Sets the file type command. |
IF | Performs conditional processing in batch programs. |
MD, MKDIR | Creates a directory. |
MOVE | Moves a file to a new location |
PATH | Sets or modifies the PATH environment |
PAUSE | Causes the command session to pause for user input. |
POPD | Changes to the drive and directory popped from the directory stack |
PROMPT | Sets or modifies the string displayed when waiting for input. |
PUSHD | Pushes the current directory onto the stack, and changes to the new directory. |
RD / RMDIR | Removes the directory. |
REM | A comment command. Unlike double-colon (::), the command can be executed. |
REN / RENAME | Renames a file or directory |
SET | Sets or displays shell environment variables |
SETLOCAL | Creates a child-environment for the batch file. |
SHIFT | Moves the batch parameters forward. |
START | Starts a program with various options. |
TIME | Displays or sets the system clock |
TITLE | Changes the window title |
TYPE | Prints the content of a file to the console. |
VER | Shows the command processor, operating system versions. |
VERIFY | Verifies that file copy has been done correctly. |
VOL | Shows the label of the current volume. |
/?
convention, causing them to write on-line usage information to their standard output and then to exit with a status code of 0.