cmd /c vs cmd /k: run a command and exit, or keep the window open
- tool
- Command Prompt (cmd)
- command
- cmd
- flag
- /c, /k (also /s, /d, /v:on)
- default
- no switch: cmd starts an interactive shell
cmd /c COMMAND starts a new command interpreter, runs the command and exits, returning the command's exit code. cmd /k COMMAND runs the command and keeps the interpreter open for more input. Use /c in scripts, scheduled tasks, shortcuts and when calling cmd built-ins (dir, mklink, del, assoc) from PowerShell or another program; use /k when a person should see the result and keep working in the window. Microsoft's reference: /c "Carries out the command specified by <string> and then exits the command processor", /k "Carries out the command specified by <string> and keeps the command processor running."
cmd /c "mklink /j C:\Data D:\Data"
cmd /k "cd /d C:\Projects & set PATH"Exit code and command chaining
The exit code of the last command becomes the exit code of cmd /c, so a caller can check %errorlevel% (cmd) or $LASTEXITCODE (PowerShell). Run in a scratch folder:
cmd /d /c "echo inner command & exit /b 7"
echo cmd /c returned %errorlevel%
cmd /d /c "ver >nul && echo first succeeded"
cmd /d /c "set X=1& echo plain: %X%"
cmd /d /v:on /c "set Y=2& echo delayed: !Y!"Output
inner command cmd /c returned 7 first succeeded plain: delayed: 2
The fourth line prints an empty value: %X% is expanded when the line is read, before set runs (here by the batch file containing the line, where an undefined variable expands to nothing). /v:on enables delayed expansion for the new interpreter and !Y! then shows the value set on the same line; see setlocal enabledelayedexpansion.
Switches
| Switch | Effect |
|---|---|
| /c STRING | run STRING, then exit with its exit code |
| /k STRING | run STRING, then stay open |
| /s | with /c or /k, always strip the first and last quote around the string and leave the rest unchanged |
| /d | do not run the AutoRun commands from the registry |
| /q | turn echo off |
| /v:on | enable delayed environment variable expansion (!VAR!) |
| /e:off | disable command extensions |
| /u, /a | output of internal commands to a pipe or file as Unicode or ANSI |
Pitfalls
- Quotes. The reference describes how cmd keeps or strips quotes after
/c: they are preserved only if/sis not used, there is exactly one set of quotes, no special characters (&<>()@^|) between them, at least one space inside, and the quoted text is the name of an executable file. Otherwise, if the string starts with a quote, that quote and the closing one are removed.cmd /c ""C:\Program Files\App\app.exe" --flag"works because of the extra outer pair. - AutoRun surprises. A command in
HKCU\Software\Microsoft\Command Processor\AutoRunruns before everycmd /cand can change the directory or print text;/dskips it in scripts. - exit vs exit /b. Inside the string,
exit /b Nends the batch context with code N; plainexit Ncloses that interpreter. Both set the exit code ofcmd /c; see check errorlevel. - Not found. A misspelled program inside
/cprints is not recognized as an internal or external command and returns 9009.
FAQ
How do I run several commands with one cmd /c?
Join them with & (always run the next), && (only if the previous succeeded) or || (only if it failed), and put the whole string in double quotes so the calling shell does not split it.
Why does my cmd /c command lose its quotes?
When the string after /c starts with a quote and does not meet all the documented conditions (one set of quotes, no special characters, a space inside, an executable name inside), cmd removes the opening quote and its closing quote. Add an extra pair of outer quotes, or use /s to make that removal predictable.
How do I call cmd /c from PowerShell?
cmd /c 'dir /b' works; the exit code is in $LASTEXITCODE afterwards. For built-in commands such as mklink, dir or assoc this is the only way, because they are not separate programs.