Skip to content

/flags/cmd/cmd-c-vs-k

cmd /c vs cmd /k: run a command and exit, or keep the window open

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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
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
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

SwitchEffect
/c STRINGrun STRING, then exit with its exit code
/k STRINGrun STRING, then stay open
/swith /c or /k, always strip the first and last quote around the string and leave the rest unchanged
/ddo not run the AutoRun commands from the registry
/qturn echo off
/v:onenable delayed environment variable expansion (!VAR!)
/e:offdisable command extensions
/u, /aoutput 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 /s is 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\AutoRun runs before every cmd /c and can change the directory or print text; /d skips it in scripts.
  • exit vs exit /b. Inside the string, exit /b N ends the batch context with code N; plain exit N closes that interpreter. Both set the exit code of cmd /c; see check errorlevel.
  • Not found. A misspelled program inside /c prints 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.

Sources