Reputation: 133
I'm trying to pipe commands using scala's sys.process library, but I noticed that #|
will return the exit code of the final process. I'm having commands earlier in the pipe fail, but the exit code of the final command is 0 as it didn't error out.
I was wondering if scala has a way to check/retrieve if previous commands in the pipe (#|) failed.
import scala.sys.process._
val p1 = ("false" #| "true").run()
assert(p1.exitValue == 1)
Bash has set -o pipefail
that will pass the non-zero exit-code of a pipe, but it just seems a bit "hacky":
val p2 = Seq("/bin/bash", "-c", "set -o pipefail && false | true").run()
assert(p2.exitValue == 1)
I was hoping there might be a better way.
Thanks, I appreciate any help :)
Upvotes: 1
Views: 578
Reputation: 48430
!!
operator throws an exception on non-zero exit code, so perhaps it can be used to pass output of one process to the input stream of another via #<
operator only on success. If we define a custom operator #|<
like so
implicit class Pipefail[T](p1: T) {
def #|<(p2: T)(implicit ev: T => ProcessBuilder): ProcessBuilder =
Try(p1.!!).map(result => (p2 #< new ByteArrayInputStream(result.getBytes))).get
}
then we could call it with
("false" #|< "true").run
which should throw
java.lang.RuntimeException: Nonzero exit value: 1
whilst
("echo Beam Me Up, Scotty" #|< "tr a-z A-Z" #|< "grep -o SCOTTY" ).run
should output uppercase SCOTTY
. This will use stringToProcess
implicit conversion, so remember to import scala.sys.process._
Upvotes: 2