Reputation: 63032
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?
Upvotes: 1
Views: 1171
Reputation: 8996
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)
Upvotes: 2