Free tools Windows power users keep installed
One-click scans. No signup required.
To write a Windows command script, save commands in a .bat or .cmd file and run it with cmd.exe. A command prompt session is interactive: you type one command, see its result, then type another. A batch file is a repeatable sequence that the command interpreter parses and executes. The modern cmd reference applies to Windows 10, Windows 11, Windows Server 2016, 2019, 2022 and 2025, and Azure Local 2311.2 and later. “NT” describes the historical Windows NT lineage; it is not a separate scripting product you need to install.
Command prompt session versus a batch file
In an existing Command Prompt window, commands run in the current shell and can change that shell’s working directory, environment variables and options. A script file stores those commands so they can be run consistently, scheduled or called by another script.
- Interactive command: type it at a prompt such as
C:>; the current session remains available. - Batch script: put commands in a text file ending in
.bator.cmd, then run the file from Command Prompt, File Explorer, Task Scheduler or another program.
Use cmd /c when a separate shell should run a command and exit. Use cmd /k when it should run the command and leave the shell open so you can inspect the result. The /d switch disables AutoRun commands, making a launch less dependent on machine or user configuration.
Start cmd.exe predictably
| Invocation | Effect | Typical use |
|---|---|---|
cmd /c "command" |
Runs the command, then exits the new shell. | One-shot automation, installers and scripts launched by another program. |
cmd /k "command" |
Runs the command and keeps the shell open. | Interactive troubleshooting or viewing output after a script finishes. |
cmd /d /c "command" |
Runs without processing configured AutoRun commands, then exits. | Controlled or reproducible launches. |
cmd /e:on or cmd /e:off |
Enables or disables command extensions for that process. | Making extension-dependent behavior explicit. |
cmd /v:on or cmd /v:off |
Enables or disables delayed environment-variable expansion. | Reading values that change inside parenthesized blocks. |
Without /d, cmd checks machine and user AutoRun registry entries before processing other settings. AutoRun can be useful in a managed environment, but it can also make the same command behave differently on two computers. Avoid casually editing the registry; Microsoft warns that incorrect edits can severely damage a system.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minute#1 Best Overall
Build a small, readable batch file
A practical starting point is:
@echo off
setlocal
set "SOURCE=C:Workinput files"
set "DEST=C:Workarchive"
if not exist "%DEST%" mkdir "%DEST%"
copy /y "%SOURCE%report.txt" "%DEST%"
if errorlevel 1 (
echo Copy failed.
exit /b 1
)
echo Copy completed.
endlocal
@echo off hides each command as it runs. The quoted set "NAME=value" form prevents accidental trailing spaces from becoming part of the value. setlocal keeps the script’s environment changes from leaking into the caller; endlocal restores the previous environment.
Quote paths and escape shell metacharacters
Always quote a path that may contain spaces:
dir "C:Program FilesCommon Files"
copy "C:ReportsApril report.csv" "D:Archive"
Characters such as &, |, <, >, parentheses and other shell metacharacters can be parsed as command syntax rather than literal argument text. Quote arguments where appropriate and use the caret (^) to escape a metacharacter when the particular parsing context requires it:
echo Price ^& tax
if exist "C:Data (old)" echo Found
Quoting is context-sensitive. A command typed directly, a line inside a batch file, a nested cmd /c command and a program that parses its own arguments do not all apply identical quote rules. The /s option also changes how a quoted command string is handled. Test nested commands with the exact executable and arguments you will deploy rather than assuming one universal quoting recipe.
Control flow with operators, pipes and redirection
| Syntax | Meaning | Example |
|---|---|---|
command1 && command2 |
Run command2 only when command1 succeeds. |
mkdir "C:Logs" && echo Directory ready |
command1 || command2 |
Run command2 only when command1 fails. |
copy source target || echo Copy failed |
command1 & command2 |
Run both in sequence regardless of the first result. | echo Starting & echo Continuing |
command | command |
Send the first command’s output to the second command as input. | dir /b | findstr /i ".log$" |
command > file |
Write standard output to a file, replacing it. | ipconfig > "C:Tempnetwork.txt" |
command >> file |
Append standard output to a file. | echo Finished >> "C:Temprun.log" |
Use parentheses to group related commands in an if, for or other compound command. Grouping changes when variables are expanded, which is why a value set inside a block can appear not to update.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Understand variable expansion and delayed expansion
Percent expansion happens while the command is parsed
%NAME% is substituted when the command or compound block is processed. It is context-sensitive in batch files and substitution is non-recursive: if one variable’s value contains another variable reference, cmd does not repeatedly expand it until a final value appears.
set "count=0"
for %%F in (*.txt) do (
set /a count+=1
echo Count is %count%
)
In this example, the whole parenthesized block can be parsed before the loop runs, so every %count% may show the original value.
Rank #3
Delayed expansion reads the current value inside a block
Enable delayed expansion explicitly with cmd /v:on or setlocal enabledelayedexpansion, then use exclamation marks:
setlocal enabledelayedexpansion
set "count=0"
for %%F in (*.txt) do (
set /a count+=1
echo Count is !count!
)
endlocal
When delayed expansion is enabled, ! becomes meaningful to the shell. Data containing literal exclamation marks can therefore be altered during parsing. Enable it only where needed, and disable or localize it when processing untrusted or punctuation-heavy text.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Keep environment changes inside a scope
setlocal localizes environment variables and command-shell options. Scopes can be nested, and the end of the batch file closes any remaining localization:
setlocal
set "MODE=test"
setlocal enabledelayedexpansion
set "TEMP_VALUE=local only"
endlocal
endlocal
Be aware that setlocal changes ERRORLEVEL: with an extension or delayed-expansion option it sets ERRORLEVEL to 0; without an option it sets it to 1. Consequently, do not run setlocal between a command and the status check that belongs to that command.
Check whether a command failed
Check the exit status immediately after the command whose result matters:
robocopy "C:Source" "D:Backup"
if errorlevel 8 (
echo Robocopy reported a failure-level result.
exit /b 1
)
echo Robocopy completed without a failure-level result.
if errorlevel N means “is the exit code greater than or equal to N,” not “is it exactly N.” For a simple success/failure branch, chaining is often clearer:
Best Value
copy "C:in.txt" "D:out.txt" && echo Success || echo Failure
Do not insert another command before the check. Commands such as setlocal, echo or a diagnostic utility can change the status you intended to inspect. If you need the numeric value for logging, capture it immediately with set "rc=%errorlevel%" and then use the saved variable.
Common failure symptoms and fixes
- “The system cannot find the path specified”: quote paths with spaces and verify the current working directory.
- A variable is unchanged inside an
iforforblock: use delayed expansion and!NAME!, or move the calculation outside the block. - A literal
&or|is treated as syntax: quote the argument or escape the character with^for that parsing context. - The script works on one machine but not another: compare AutoRun behavior, command extensions, delayed-expansion settings, PATH and the working directory; use
cmd /dwhen AutoRun must not run. - An error check reports the wrong result: move
if errorleveldirectly after the command and beforesetlocalor other commands.
Know the environment-variable limits
Microsoft’s 2025 cmd reference documents a maximum individual environment-variable size of 8,192 bytes. It also documents a maximum total size of 65,536 characters for all environment variables in a process, including names, values and equal signs. These are implementation limits, not recommended targets; large data should normally be stored in files rather than environment variables.
When to use PowerShell instead
Batch files remain useful for small, built-in Windows command sequences and compatibility with existing automation. For richer data handling, structured objects, error handling and modern automation, Microsoft says, “Users seeking more advanced capabilities are encouraged to explore PowerShell for enhanced scripting and automation.”
Further reading
Windows NT Shell Scripting by Tim Hill is a historical book-length reference. It can help explain older NT-era batch techniques, but verify the edition and availability before relying on it for current Windows behavior.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




