Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling an external command as a subprocess in Scala

In Python, if I want to call an external command as a subprocess, I do the following:

from subprocess import Popen, PIPE
cmd = ['cat', '-be']
out, err = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate("some input")

What's the standard way to do the same in Scala? Using Java's ProcessBuilder I came up with the following, but it's pretty ugly:

def communicate(cmd: List[String], input: Option[String] = None): (String, String) = {

    val command = new java.util.ArrayList[String]()
    cmd.foreach(command.add(_))

    val builder = new ProcessBuilder(command)
    val process = builder.start()

    val stdinWriter = new java.io.PrintWriter((new java.io.OutputStreamWriter(new java.io.BufferedOutputStream(process.getOutputStream()))), true);
    val stdoutReader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()))
    val stderrReader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getErrorStream()))

    input.foreach(stdinWriter.write(_))
    stdinWriter.close()

    def read(reader: java.io.BufferedReader): String = {
        val out = new ListBuffer[String]
        var line: String = reader.readLine()
        while (line != null) {
            out += line
            line = reader.readLine()
        }
        return out.result.mkString("\n")
    }

    val stdout = read(stdoutReader)
    val stderr = read(stderrReader)

    stdoutReader.close()
    stderrReader.close()

    return (stdout, stderr)

}

val (catout, caterr) = communicate(List("cat", "-be"), Some("some input"))
val (pwdout, pwderr) = communicate(List("pwd"))

Is there a better alternative built into Scala already?

like image 419
dhg Avatar asked Dec 17 '22 13:12

dhg


2 Answers

The answer here How does the “scala.sys.process” from Scala 2.9 work? shows how to use the new Scala 2.9 scala.sys.process.Process. If you don't use 2.9 you can use the process part of sbt; which the Scala process originates from.

like image 55
thoredge Avatar answered Jan 13 '23 12:01

thoredge


Using the OS-Lib library, your code can be written as the following Scala:

@ val res = os.proc("cat", "-be").call(stdin = "some input")
res: os.CommandResult = CommandResult(0, List(Left(     1   some input)))

@ res.out.string
res3: String = "     1\tsome input"

@ res.err.string
res4: String = ""
like image 33
Li Haoyi Avatar answered Jan 13 '23 10:01

Li Haoyi