How to use && inside echo without using quotes? - windows

I want to write a command like this inside a file using only cmd.exe (with ShellExecute, C++),
It's something like this:
timeout /t 10 && start cmd.exe /C "ssh -o ..."
I tried using this:
echo timeout /t 10 && start cmd.exe /C "ssh -o ..." > myfile.bat
but it cuts when it reaches && and I can't use quotes on the entire string, so what should I do? I don't want to use anything other than cmd.exe, and I just want to write this to a .bat file.
How can I solve this?

1) Use disappearing quotes.
FOR %%^" in ("") do (
echo %%~"timeout /t 10 && start cmd.exe /C "ssh -o ..." %%~" > myfile.bat
)
2) Escape the special characters
echo timeout /t 10 ^&^& start cmd.exe /C "ssh -o ..." > myfile.bat
3) Use delayed expansion
setlocal EnableDelayedExpansion
set "line=timeout /t 10 && start cmd.exe /C "ssh -o ...""
echo !line! > myFile

Related

Start /b command is not completing the command and exit SSH straightaway

I am using ssh to run a bat file which will be running multiple commands in parallel as below:
(
start "" cmd /c "cd "C:/Users/desktop" && python -m command"
start "" cmd /c "cd "C:/Users/desktop" && python -m command"
) | pause >nul
the bat file is able to run however, i requrie the output of the python to be shown in the command window. I have tried to include /b in the command
(
start /b "" cmd /c "cd "C:/Users/desktop" && python -m command"
start /b "" cmd /c "cd "C:/Users/desktop" && python -m command"
) | pause >nul
However, the above does not work. It exited before finishing the run of the python commands.

cmd.exe /C unable to run the command

I'm running below command which is working successfully if I run it manually via command prompt
SET filename=testfile_26032021.txt && SET newfilename=%filename:~9,8% && copy C:\test\updatedtestfile_%newfilename%.txt C:\test\updatedtestfile_%newfilename%.txt.temp
But when I run this through an external call I get an error
The system cannot find the file specified.
Here's the command I'm running
cmd.exe /C SET filename=testfile_26032021.txt && SET newfilename=%filename:~9,8% && copy C:\test\updatedtestfile_%newfilename%.txt C:\test\updatedtestfile_%newfilename%.txt.temp
I caught the error by changing the flag from /C to /K.
Any idea what is wrong with this command?
You can't do like this SET filename=testfile_26032021.txt && SET newfilename=%filename:~9,8% because %filename% is expanded at parsing time where it's not available yet. You must enable delayed expansion and tell cmd to expand the command later with !variable_name!. Besides && ends the previous command so your whole thing is parsed as 3 commands:
cmd.exe /C SET filename=testfile_26032021.txt
SET newfilename=%filename:~9,8%
copy C:\test\updatedtestfile_%newfilename%.txt C:\test\updatedtestfile_%newfilename%.txt.temp
So you must quote the command like this
cmd.exe /V:on /C "SET "filename=testfile_26032021.txt" && SET "newfilename=!filename:~9,8!" && copy C:\test\updatedtestfile_!newfilename!.txt C:\test\updatedtestfile_!newfilename!.txt.temp"
or
cmd.exe /C "setlocal enabledelayedexpansion && SET filename=testfile_26032021.txt && SET newfilename=!filename:~9,8! && copy C:\test\updatedtestfile_!newfilename!.txt C:\test\updatedtestfile_!newfilename!.txt.temp"
See also
Windows command prompt: Using a variable set in the same line of a one-liner
How set a variable and then use it in the same line in command prompt
Setting and using variable within same command line in Windows cmd.exe

Why is here difference in this 2 cases of command execution?

I need to run two commands in paralel with double quotation (the simple one won't work in my case) and wait for the results. But when I do this, I get a different behavior with double qouted execution (my command simply won't run for unknown reason).
I've simplified the problem to this example:
(
start "task1" cmd /C "timeout /t 5 /nobreak > nul"
start "task2" cmd /C ""timeout /t 8 /nobreak > nul""
) | pause
You can see that in the later case the counter will count down, but not in the first case
Waiting for 8 seconds, press CTRL+C to quit ...
Question:
What causes the change between those two cases?
How can this changed behavior avoided?
In my special case:
When I run this everything works fine:
start "task1" cmd /C ""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "^<WizardValues^> ^<Module^>D:\long path\aaa.yxwz^</Module^> ^<Value name='Drop Down (31)'^>2019-08^</Value^> ^</WizardValues^>" > outp1.txt "
When I put the simple version into a complex one the execution simply fails:
(
start "task1" cmd /C ""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "^<WizardValues^> ^<Module^>D:\long path\aaa.yxwz^</Module^> ^<Value name='Drop Down (12)'^>2019-08^</Value^> ^</WizardValues^>" > outp1.txt "
start "task2" cmd /C ""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "^<WizardValues^> ^<Module^>D:\long path\bbb.yxwz^</Module^> ^<Value name='Drop Down (34)'^>2019-07^</Value^> ^</WizardValues^>" > outp2.txt "
) | pause
Question:
How this change in behavior is similar to the above example?
Concerning your test scenario:
In cmd /C "timeout /t 5 /nobreak > nul" the redirection operator > is hidden from the hosting cmd instance (the one that runs the code of your batch file), so it becomes executed in the inner cmd instance.
In cmd /C ""timeout /t 5 /nobreak > nul"" the > is exposed to the hosting cmd instance, so redirection is executed there and the inner one does not receive the > nul part.
(Though what surprises me a bit is that no syntax error arises due to the double-quotation; I could imagine that the second start command actually receives something like ""timeout /t 5 /nobreak to execute, where it seems to remove the leading "" from, but I am not quite sure.)
Concerning your special case:
Forget about escaping within your XML-like string, just escape the outer quotes and the redirection operator.
Running the program alone:
start "task1" cmd /C ^""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "<WizardValues> <Module>D:\long path\aaa.yxwz</Module> <Value name='Drop Down (31)'>2019-08</Value> </WizardValues>" ^> "outp1.txt"^"
Running the program in the pipe (|) requires double-escaping, since either side is executed by cmd /S /D /c on its own here:
(
start "task1" cmd /C ^^^""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "<WizardValues> <Module>D:\long path\aaa.yxwz</Module> <Value name='Drop Down (12)'>2019-08</Value> </WizardValues>" ^^^> "outp1.txt"^^^"
start "task2" cmd /C ^^^""D:\Program Files\Alteryx\bin\AlteryxEngineCmd.exe" "<WizardValues> <Module>D:\long path\bbb.yxwz</Module> <Value name='Drop Down (34)'>2019-07</Value> </WizardValues>" ^^^> "outp2.txt"^^^"
) | pause ^> nul
Unfortunately you cannot just omit the (escaped) outer pair of quotation marks, because cmd is not quite intelligent when handling them. Something like cmd /C "program.exe" "quoted string" leaves the command line program.exe" "quoted string behind, which is of course invalid syntax.
N. B.:
Usually an external program can be started using without cmd /C, but in your situation you are using output redirection >, which is a thing internal to cmd, that is why you need it.

How to run commands on another cmd

I want to run commands on 2 cmds while opening the same file, like if I open a .bat file It opens 2 cmd and they run 2 differents commands (1 each). It's possible to do that?
If I got you right this is what you want to do, note it's a batch file:
#echo off
start cmd /c "echo 1st command && pause"
start cmd /c "echo 2nd command && pause"
Read about cmd here and about start here. The following switches of the cmd command can be considered:
/c: Carries out the command specified by string and then stops.
/k: Carries out the command specified by string and continues.
Instead of using /k I used /c with a pause command to show the concatenation of 2 commands here.
To concate 2 commands use commandA && commandB which is described here at ss64 which is a great site when it comes to batch scripting:
commandA && commandB: Run commandA, if it succeeds then run commandB
As requested another example with cd, dir and pause could look like:
#echo off
start cmd /c "cd C:\Users\ && dir && pause"
start cmd /c "cd C:\ && dir && pause"
It changes the directory, prints the directory list and wait for use input.

%ERRORLEVEL% is not working incase multiple commands on a Single line

I am trying the below commands and want to get exit of my process(%ERRORLEVEL%). But it is returning previous(last) executed exit code result of sample.exe. I want to get exit code of current command. My requirement is to execute multiple commands in single line*(not batch script)*.
Command:
cmd /c sample.bat "test" > c:\ouput.log & echo %ERRORLEVEL% > c:\returnCode.log
I even tried using "setlocal enableDelayedExpansion" like below. Still It is not returning the exit code of current command
cmd /c setlocal enableDelayedExpansion & sample.bat "test" > c:\ouput.log & echo %ERRORLEVEL% > c:\returnCode.log
Please let me know the way to get current command's exit code.
This should work:
cmd /V:ON /c sample.exe "test" > c:\ouput.log ^& echo !ERRORLEVEL! ^> c:\returnCode.log
/V:ON switch have the same effect of setlocal EnableDelayedExpansion. For further details, type: cmd /?
EDIT: Small error fixed, the & character must be escaped with ^, otherwise, the echo !ERRORLEVEL! command is not executed in the cmd /V:ON !!!
EDIT: Escaping the echo redirection via ^> causes just that echo to be piped into the log. If you do not escape that, the entire command is piped there, i.e. including the stdout stream from "sample.exe".
cmd /c sample.exe "test" > c:\ouput.log & call echo %%ERRORLEVEL%% > c:\returnCode.log
Should work for you. See endless SO items related to delayedexpansion
Thank for your response. I am able to get the exit code of current executed command with below command, only when I run through WMI class(Win32_Process). Using WMI client, I am executing the below command on Remote machine and it is working fine i.e. able to write exit code in Retrun.txt
Command:
cmd /V:ON /c sample.bat "test" > c:\Output.txt & echo !ERRORLEVEL! > c:\Return.txt
But if I run the same command in command prompt of the same remote machine, it is printing "!ERRORLVEL!" in Return.txt instead of "sample.bat" exit code.
I am curious to know why it is not working if I run from Command prompt of the same machine locally.

Resources