1

I am looking for how to submit a string to external bash verbatim. Bash should handle wildcard expansion and escaping.

The testing is with the process library:

import sys.process._

That imports the required process DSL implicits into scope.

Let us try an escaping test: here is the desired result run on the bash shell:

$echo -ne 'abc\t\n' | tr '\t' 'T'
abcT
$

Let us try in the sys.process:

scala> "echo -ne 'abc\t\n' | tr '\t' 'T'" !!
warning: there were 1 feature warning(s); re-run with -feature for details
res16: String =
"-ne 'abc ' | tr ' ' 'T'
"

Fail ..pretty different than on command line..

Now let us try an expansion test (OS/X flavor):

scala> "open /shared/adm*" !!
warning: there were 1 feature warning(s); re-run with -feature for details
The file /shared/adm* does not exist.
java.lang.RuntimeException: Nonzero exit value: 1
    at scala.sys.package$.error(package.scala:27)
    at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:131)
    at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:101)

Fail.. Here the wildcard expansion was not performed.

So .. should I resort to the old java Process way - which is to execute "bash -c" and then send in the entire command line?

2
  • You are asking for features that bash implements like pipes and wild cards so run them through bash! See scala-lang.org/api/2.11.5/… for some enlightenment. Commented May 30, 2015 at 15:11
  • @DavidWeber That page does not address either expansion or escaping- and I was already aware of pipes and wildcards support as described. Commented May 30, 2015 at 15:54

1 Answer 1

2

Note: There is a difference between running an external command (sed, cat, ls, etc.) and commands that are build in bash such as cd, |, and wildcards. Using the process package does not allow you to run bash commands from strings.

Here is my attempt to implement what you want in Scala (2.10). The first approach only uses methods provided by the process package. The second approach is indirectly invoking bash to run the entire command.

import sys.process._

val f = (Seq("echo", "-n", "abc\t\n") #| "tr '\\t' 'T'").!!.trim
println(f)

val g = Seq("/bin/sh", "-c", "echo 'abc\t\n' | tr '\t' 'T'").!!.trim
println(g)
Sign up to request clarification or add additional context in comments.

2 Comments

i was hoping to avoid complicating the call to process: the above will work but then loses the convenience of just "create a command string and fire away"
I agree it might not be as short as running it directly from bash, but I feel it is much shorter and less verbose than using Java Process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.