How to use 'and' and 'or' when running external commands in Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 12.16, “How to use 'and' and 'or' when running external commands in Scala.”

Problem

You want to use the equivalent of the Unix && and || commands in Scala to perform an if/then/else operation when executing external commands.

Solution

Use the Scala operators #&& and #||, which mirror the Unix && and || operators:

val result = ("ls temp" #&& "rm temp" #|| "echo 'temp' not found").!!.trim

This command can be read as, “Run the ls command on the file temp, and if it’s found, remove it, otherwise, print the ‘not found’ message.”

In practice, this can be a little more difficult than shown, because these commands usually involve the use of a wildcard operator. For instance, even if there are .scala files in the current directory, the following attempt to compile them using #&& and #|| will fail because of the lack of wildcard support:

scala> ("ls *.scala" #&& "scalac *.scala" #|| "echo no files to compile").!
ls: *.scala: No such file or directory
no files to compile
res0: Int = 0

To get around this problem, use the formula shared in Recipe 12.17, “Handling Wildcard Characters in External Commands” running each command in a shell (and also separating each command to make the #&& and #|| command readable):

#!/bin/sh
exec scala "$0" "$@"
!#
import scala.sys.process._

val filesExist = Seq("/bin/sh", "-c", "ls *.scala")
val compileFiles = Seq("/bin/sh", "-c", "scalac *.scala")

(filesExist #&& compileFiles #|| "echo no files to compile").!!

That script compiles all .scala files in the current directory.