River
River

Reputation: 133

Is there a way to get the exit code of an earlier piped Scala Process (#|)?

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

Answers (1)

Mario Galic
Mario Galic

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

Related Questions