Proper escaping quotes from bash to batch - bash

I'm trying to start from a cygwin-bash context a batch process.
But my quotes are removed or escaped with backslashes.
Sample:
npp="\"$(cygpath -w "/cygdrive/c/Program Files (x86)/Notepad++/notepad++.exe")\""
echo "$npp"
echo cmd /c "echo start \"\" $npp"
cmd /c "echo start \"\" $npp"
Output:
"C:\Program Files (x86)\Notepad++\notepad++.exe"
cmd /c echo start "" "C:\Program Files (x86)\Notepad++\notepad++.exe"
start \"\" \"C:\Program Files (x86)\Notepad++\notepad++.exe\"
The first and second line is the expected output.
But in the third line there are unwanted backslashes.
I suppose that the bash shell added these slashes always, but later they are removed by the bash shell again, but in the case of a batch-cmd context there is no process to remove the backslashes.
My question is, how to avoid the backslashes or how to remove them in the batch context?

I don't have a bash instance at hand, but tested on busybox (I know, not the same, just a test)
W:/ $ word='"C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"'
W:/ $ eval "cmd /c echo start \"\" $word"
start "" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"
W:/ $ word="C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"
W:/ $ eval "cmd /c echo start \"\" \"$word\""
start "" "C:\Program Files (x86)\Microsoft Office\Office14\WINWORD.EXE"

To start NPP in notepad mode with foo.txt opened.
Use the cygpath --dos option, and the cygstart --verbose option:
cygstart --verbose --wait $(cygpath --dos "/cygdrive/c/Program Files (x86)/Notepad++/notepad++.exe") -multiInst -nosession foo.txt
or let cygstart do the cygpath for us:
cygstart --verbose --wait "/cygdrive/c/Program Files (x86)/Notepad++/notepad++.exe" -multiInst -nosession foo.txt
or just use cmd if it is in your path, otherwise:
/cygdrive/c/Windows/system32/cmd.exe /c start '""' /I /WAIT 'c:\Program Files (x86)\Notepad++\notepad++.exe' -multiInst -nosession -noPlugin -notabbar foo.txt

I found one solution, but it seems to be a bit ugly.
npp="$(cygpath -w "/cygdrive/c/Program Files (x86)/Notepad++/notepad++.exe")"
cmd /c "set q=\"\" & (call set q=%q:~1,1%) & call echo start %q%%q% %q%$npp%q%"
The second line simply creates in the variable q a single quote sign.
First q is set to \"\" and the (call set q=%q:~1,1%) sets q with the second character of the previous content of q.
And the call ...%q% uses these quotes.
But as said before, this seems not to be a desirable solution.

Related

How to use && inside echo without using quotes?

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

How do I emulate a "wrapper script" on Windows?

On Linux, when I want to prepare the environment of a program before starting it, I'm using a wrapper script:
export JAVA_HOME=...
cd /some/folder
exec ./tool "$#"
How would I do the last line, especially the "$#", on Windows?
Note: I'm wrapping commands which take a lot of arguments (like java or mvn), so I need a solution which works for > 10 arguments.
Being able to exec would be nice but is only a minor concern.
Probably something like:
#echo off
setlocal enableextensions
set JAVA_HOME=...
cd ...
start "" .\sometool %*
endlocal
Setlocal localizes environment changes to the script (see setlocal /? for details), and %* means 'all script parameters'. The start command is a cmd.exe command that spawns an executable.
The start command has odd parsing rules; the first quoted string on its command line is considered to be a console window title, which is superfluous if you are not spawning a console window. This means that a command like this won't work as expected:
start "C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"
If you run this command, you will spawn a new instance of cmd.exe with the quoted string as its console window title, which is clearly not what was intended. Instead, you have to write this:
start "" "C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"

Using cygwin to netively execute cmd command and redirect stdout

Using cygwin on Windows 7, need to:
execute a command in cmd
return immediately (using START)
redirect stdout to a file
I've tried (executed in cygwin):
cmd /C "START cmd /C \"executableFileName -f -n 100 > logFilePath.txt\""
And many variations of the above line, but nothing worked.
I don't have cygwin, so I cannot test. But try the following.
cmd /c start cmd /c "executableFileName -f -n 100 >logFilePath.txt"
The quotes around the command following /c are not required, so you don't need them in the first cmd /c. They are useful in the second cmd /c to prevent the redirection from activating until the final cmd is executed.
Regarding your original code - the escape character for cmd.exe is ^, not \, and you cannot escape a quote once quoting has begun. That is why I opted not to include any quotes in the outer most cmd /c

Correct quoting for cmd.exe for multiple arguments

I want to call
cmd /c "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.com" mysolution.sln /build "release|win32"
Unfortunately this does not work, because I get the error:
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
As I understand, I need quoting for the spaces and quotes for the |, but I am only allowed to use the quotes once.
Any ideas how to quote this command line call correctly?
Note the "" at the beginning and at the end!
Run a program and pass a Long Filename
cmd /c write.exe "c:\sample documents\sample.txt"
Spaces in Program Path
cmd /c ""c:\Program Files\Microsoft Office\Office\Winword.exe""
Spaces in Program Path + parameters
cmd /c ""c:\Program Files\demo.cmd"" Parameter1 Param2
Spaces in Program Path + parameters with spaces
cmd /k ""c:\batch files\demo.cmd" "Parameter 1 with space" "Parameter2 with space""
Launch Demo1 and then Launch Demo2
cmd /c ""c:\Program Files\demo1.cmd" & "c:\Program Files\demo2.cmd""
CMD.exe (Command Shell)
Spaces are used for separating Arguments. In your case C:\Program becomes argument. If your file path contains spaces then add Double quotation marks. Then cmd will recognize it as single argument.
Spaces are horrible in filenames or directory names.
The correct syntax for this is to include every directory name that includes spaces, in double quotes
cmd /c C:\"Program Files"\"Microsoft Visual Studio 9.0"\Common7\IDE\devenv.com mysolution.sln /build "release|win32"

cmd.exe /k switch

I am trying to switch to a directory using cmd and then execute a batch file
e.g.
cmd /k cd "C:\myfolder"
startbatch.bat
I have also tried (without success)
cmd cd /k cd "C:\myfolder" | startbatch.bat
Although the first line (cmd /k) seems to run ok, but the second command is never run. I am using Vista as the OS
Correct syntax is:
cmd /k "cd /d c:\myfolder && startbatch.bat"
ssg already posted correct answer. I would only add /d switch to cd command (eg. cd /d drive:\directory). This ensures the command works in case current directory is on different drive than the directory you want to cd to.
cmd cd /k "cd C:\myfolder; startbatch.bat"
or, why don't you run cmd /k c:\myfolder\startbatch.bat, and do cd c:\myfolder in the .bat file?
I can't see an answer addressing this, so if anyone needs to access a directory that has space in its name, you can add additional quotes, for example
cmd.exe /K """C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"" & powershell.exe"
From PowerShell you need to escape the quotes using the backquote `
cmd.exe /K "`"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat`" & powershell.exe"
Notice the escaped quotes
`"
inside the path string:
"`"C:\my path\`""
This will execute the proper command in cmd, i.e. the path surrounded with quotes which should work.
The example command above will initialise the MSVC developer command prompt and go back to PowerShell, inheriting the environment and giving access to the MSVC tools.
You can use & or && as commands separator in Windows.
Example:
cmd cd /K "cd C:\myfolder && startbatch.bat"
I give this as an answer because I saw this question in a comment and cannot comment yet.
cmd /k "cd c:\myfolder & startbatch.bat"
works, and if you have spaces:
cmd /k "cd "c:\myfolder" & startbatch.bat"
As I understand it, the command is passed to cmd as "cd "c:\myfolder" & startbatch.bat", which is then broken down into cd "c:\myfolder" & startbatch.bat at which point the remaining " " takes care of the path as string.
You can also use &&, | and || depending on what you want to achieve.

Resources