How to redirect the STDOUT and STDIN of external commands

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 12.15, “How to redirect the STDOUT and STDIN of external commands in Scala.”

Problem

You want to redirect the standard output (STDOUT) and standard input (STDIN) when running external system commands in a Scala application. For instance, you may want to redirect STDOUT to log the output of an external command to a file.

Solution

Use #> to redirect STDOUT, and #< to redirect STDIN.

When using #>, place it after your command and before the filename you want to write to, just like using > in Unix:

import sys.process._
import java.io.File

("ls -al" #> new File("files.txt")).!
("ps aux" #> new File("processes.txt")).!

You can also pipe commands together and then write the resulting output to a file:

("ps aux" #| "grep http" #> new File("http-processes.out")).!

Get the exit status from a command like this:

val status = ("cat /etc/passwd" #> new File("passwd.copy")).!
println(status)

You can also download a URL and write its contents to a file:

import sys.process._
import scala.language.postfixOps
import java.net.URL
import java.io.File

new URL("http://www.google.com") #> new File("Output.html") !

I don’t redirect STDIN too often, but this example shows one possible way to read the contents of the /etc/passwd file into a variable using #< and the Unix cat command:

import scala.sys.process._
import java.io.File

val contents = ("cat" #< new File("/etc/passwd")).!!
println(contents)

Discussion

The #> and #< operators generally work like their equivalent > and < Unix commands, though you can also use them for other purposes, such as using #> to write from one ProcessBuilder to another, like a pipeline:

val numLines = ("cat /etc/passwd" #> "wc -l").!!.trim
println(numLines)

The ProcessBuilder Scaladoc states that #> and #< “may take as input either another ProcessBuilder, or something else such as a java.io.File or a java.lang.InputStream.”

As mentioned, the Scala process commands are consistent with the standard Unix redirection symbols, so you can also append to a file with the #>> method:

// append to a file
("ps aux" #>> new File("ps.out")).!

Regarding the use of the URL and File classes, the Scaladoc states that instances of java.io.File and java.net.URL can be used as input to other processes, and a File instance can also be used as output. This was demonstrated in the Solution with the ability to download the contents from a URL and write it to a file with the #> operator.

See Also