Search code examples
javagroovyprocessexternal

Calling external process from Groovy/Java gives unexpected result


From Groovy/Java I try to execute following command: cmd /c echo mytext.

import java.nio.charset.Charset

println(Charset.defaultCharset().displayName()) //returns windows-1250
//in console chcp returns 852

def arg = "/c echo mytext"
def pb = new ProcessBuilder("cmd", arg)
def proc = pb.start()

def stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream(), "CP852"))
def stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "CP852"))

def line = null
println("Here is the standard output of: cmd " + arg)
while ((line = stdInput.readLine()) != null) {
    println(line)
}

println("Here is the standard error of the command (if any):")
while ((line = stdError.readLine()) != null) {
    println(line)
}

Groovy: 2.4.21, 3.0.9

Java: zulu11.50.19-ca-fx-jdk11.0.12-win_x64

The result is mytext" (including ending double quote). I cannot figure out why the double qoute is there. Can anybody help to explain me why is it there?

Thank you.


Solution

  • in short: ProcessBuilder will wrap each argument that contains spaces with double quotes

    so, ProcessBuilder("cmd", "/c echo mytext") actually runs cmd "/c echo mytext"

    try this command in command prompt:

    c:\> cmd "/c echo mytext"
    mytext"
    

    ^^^ that's exactly what you have in your result

    question why cmd interprets arguments this way must be addressed to microsoft - maybe there is a logical explanation

    however echo is not parsing arguments and outputs argument line as is

    c:\> echo "my text"
    "my text"
    
    c:\> echo my text
    my text
    

    means that correct answer for echo my text: ProcessBuilder("cmd", "/c", "echo my text")


    let me suggest a groovy variant for your code:

    def out = {s-> print(s)} as Appendable
    def err = {s-> print(s)} as Appendable
    
    def command = ['cmd', '/c', 'echo my text']
    def proc = command.execute()
    
    proc.waitForProcessOutput(out,err)