0

When I use the cmd command with two actions anded together, the spaces are removed from the second action and then doesn't run correctly. When I run

C:\>cmd /C "set "MYVAR=MYVAL" && echo %MYVAR%"

I expect

MYVAL

But I get

'echo%MYVAR%' is not recognized as an internal or external command,
operable program or batch file.
%MYVAR%

Why is this happening?

UPDATE

I have figured what is causing the problem, but I don't know how to fix it.

I created a batch file I called .cmdrc.bat that runs whenever I open a new cmd window. Effectively giving me custom functions and aliases with DOSKEY. This was causing problems with programs that launched their own cmd window, so I tried to detect if cmd was opened with a program or by the user, and then only run if a user launched it.

To do this I stripped spaces and quotes from %COMSPEC% and %CMDCMDLINE% and compared them. But for some reason, this appears to be changing the value of %CMDCMDLINE% to the version without spaces, causing the original issue.

Here is the relevant code:

:: only run this script if cmd.exe was launched by the user and not a program
:: this is done by checking if this prompt was launched with options

:: get the command that user would run and remove any spaces or double quotes
set cmdloc=%COMSPEC%
set cmdloc=%cmdloc: =%
set cmdloc=%cmdloc:"=%
:: get the command that was run to launch this instance and remove any spaces or double quotes
set cmdcall=%CMDCMDLINE%
set cmdcall=%cmdcall: =%
set cmdcall=%cmdcall:"=%
:: now compare them and exit if they are not the same
if /I not "%cmdloc%" == "%cmdcall%" (exit /B)

:: no flags were used when launching this instance of cmd.exe,
:: assume it was launched by the user and run all following commands

Why is %CMDCMDLINE% updating with the new value?

What is a better way to detect if the user launched cmd?

Community
  • 1
  • 1
Trevin Avery
  • 2,751
  • 2
  • 20
  • 31
  • 1
    when I execute it, the output is just `%MYVAR%`([as expected](https://stackoverflow.com/a/30284028/2152082)) – Stephan Jul 17 '19 at 17:33
  • also - what program are you launching this batch file with? if you're just running a batch file there's no need for the extra `cmd` stuff at all. – mael' Jul 17 '19 at 17:46
  • @meal' I'm just running the command in cmd. I'm not currently launching it from a program or in a batch file. – Trevin Avery Jul 17 '19 at 17:50
  • try throwing it in a batch file (I added that to my answer) and see if you get the same error – mael' Jul 17 '19 at 18:00
  • 2
    try to use the preferred syntax for your `set` commands (like `set "cmdcall=%CMDCMDLINE%"` etc). – Stephan Jul 17 '19 at 18:23
  • Are you sure that you really use `set cmdcall=%cmdcall: =%` and not `set cmdcall=%cmdcmdline: =%`, because the second variant would change the content of cmdcmdline. The cmdcmdline variable is the only one that will be changed by using string manipulation expressions! – jeb Jul 17 '19 at 19:34
  • @Stephan Ok, I added quotes around each set command and now it prints `%MYVAR%\nMYVAL`. Why is it printing `%MYVAR%` at all? – Trevin Avery Jul 17 '19 at 20:22
  • @jeb I pasted the actual code that I'm running. – Trevin Avery Jul 17 '19 at 20:24

2 Answers2

1

You need another cmd /C:

cmd /C "set "MYVAR=MYVAL" && cmd /C "echo %MYVAR%"

You can add/subtract quotes from the second command and it still seems to work.

or try throwing it in a batch file:

@echo off

set "MYVAR=MYVAL"

echo %MYVAR%

pause

Reference: cmd

mael'
  • 453
  • 3
  • 7
0

The whole line is parse at once, so echo %MYVAR% echoes the value of %MYVAR%before setting the variable (resulting in an empty variable - therefore the output is a literal %MYVAR%. You need delayed expansion to make it work:

cmd /v:on /c "set "MYVAR=MYVAL" & echo !MYVAR!"

Another way to go is to implement a second layer of parsing with:

cmd /C "set "MYVAR=MYVAL" & call echo %MYVAR%"

or even with:

cmd /C "set "MYVAR=MYVAL" & cmd /C "echo %MYVAR%""

(thanks @mael', I haven't seen this solution so far)

(the double double-quote at the end is actually correct. It's cmd /c "command line", where command line is set "MYVAR=MYVAL" && cmd /C "echo %MYVAR%")

Note: && works as "if previous command (set) was successful, then". Here a simple &("and then") is sufficient.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • 1
    Should `cmd /C "set "MYVAR=MYVAL" & call echo %MYVAR%"` not actually read `cmd /C "set "MYVAR=MYVAL" & call echo %^MYVAR%"` in order to work even when `MYVAR` is already defined (given that `^MYVAR` is not, of course)? (and the same also for the `cmd /C` solution) – aschipfl Jul 17 '19 at 20:36