As reported here Execute external command
in order to run an external shell command or script in Scala the right code should be:
import scala.sys.process._
val cmd = "ls -l /home" // Your command
val output = cmd.!! // Captures the output
I've noticed this works for some commands but not for others like "java -version" (especially if they have dash "-" before arguments)
Is there a correct way to execute commands like "python --version" or a more complex python script like "python /path/to/my_script.py -x value -y value" ?
Seems to work with dashes
$ scala
Welcome to Scala 2.13.6 (Eclipse OpenJ9 VM, Java 1.8.0_292).
Type in expressions for evaluation. Or try :help.
scala> import scala.sys.process._
import scala.sys.process._
scala> "java -version".!!
openjdk version "1.8.0_292"
...
scala> "python3 --version".!!
val res1: String =
"Python 3.8.5
"
Related
Inside a program - not the REPL - is it possible to introduce a string variable to represent the shell command to be executed ?
import sys.process._
val npath = opath.substring(0,opath.lastIndexOf("/"))
s"rm -rf $npath/*" !
s"mv $tmpName/* $npath/" !
The compiler says:
:103: error: type mismatch;
found : String
required: scala.sys.process.ProcessLogger
s"mv $tmpName/* $npath/" !
^
Note that in the REPL this can be fixed by using
:power
But .. we're not in the REPL here.
I found a useful workaround that mostly preserves the intended structure:
Use the
Seq[String].!
syntax. But by using spaces as a delimiter we can still write it out in a kind of wysiwig way
import sys.process._
val npath = opath.substring(0,opath.lastIndexOf("/"))
s"rm -rf $npath/*".split(" ").toSeq.!
s"mv $tmpName/* $npath/".split(" ").toSeq.!
The limitation here is that embedded spaces in the command would not work - they would require an explicit Seq of each portion of the command.
Here is a bit nicer if there were a set of commands to run:
Seq(s"rm -rf $npath/*",s"mv $tmpName/* $npath/").foreach{ cmd=>
println(cmd)
cmd.split(" ").toSeq.!
}
As can be seen in the following console session, the same command invoked from Scala produces different results than when run in the terminal.
~> scala
Welcome to Scala 2.12.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_172).
Type in expressions for evaluation. Or try :help.
scala> import sys.process._
import sys.process._
scala> """emacsclient --eval '(+ 4 5)'""".!
*ERROR*: End of file during parsingres0: Int = 1
scala> :quit
~> emacsclient --eval '(+ 4 5)'
9
Has anyone encountered this issue and/or know of a work around?
I thought this may have been a library bug, so opened an issue as well: https://github.com/scala/bug/issues/10897
It seems that Scala's sys.process api doesn't support quoting. The following works: Seq("emacsclient", "--eval", "(+ 4 5)").!.
I want use Scala like Python, so I install REPL in Sublime Text(Os is win8)
Everytime in REPL, I have to
scala> :load <my file>
, so I think it's inconvenient.
And I can't change
scala> :settings -d <路径名>
in Chinese directory.
I'm confused whether I can't change Scala script's directory with non-english language.
Thanks a lot!
If you use sbt then you can define initial commands when you launch the console.
yourproject/build.sbt:
// build.sbt
name := "initial-commands-example"
initialCommands := "import Foo._"
yourproject/script.scala:
// script.scala
object Foo {
def hello(name: String) = s"hello $name"
val msg = hello("world")
}
Inside yourproject, run sbt console, and you will have everything in Foo available inside that repl. See sbt initialCommands docs for more information.
I want to use Jcurses with Scala on a 64-bit Ubuntu.
Unfortunately i didn't find any tutorial about this subject. Can anybody help me!
My test program "testjcurses.scala"
import jcurses.system._
object TestJcurses {
def main(args:Array[String]) {
println("okay")
Toolkit.init()
}
}
I processed it the following way:
fsc -cp ~/software/Java/jcurses/lib/jcurses.jar:~/software/Java/jcurses/src -d . -Djava.library.path=~/software/Java/jcurses/lib testjcurses.scala
scala -cp ~/software/Java/jcurses/lib/jcurses.jar:~/software/Java/jcurses/src:. -Djava.library.path=~/software/Java/jcurses/lib TestJcurses
The result is:
okay
java.lang.NullPointerException
at jcurses.system.Toolkit.getLibraryPath(Toolkit.java:97)
at jcurses.system.Toolkit.<clinit>(Toolkit.java:37)
at TestJcurses$.main(testjcurses.scala:9)
at TestJcurses.main(testjcurses.scala)
..........
Can anybody help me?
Unfortunately you can't use ~ in bash like that — ~ is expanded to your home dir only right after an (unquoted) space (technically, at the beginning of a bash word, but "after a space" is the simple version). Look how your command line is expanded:
$ echo scala -cp ~/software/Java/jcurses/lib/jcurses.jar:~/software/Java/jcurses/src:. -Djava.library.path=~/software/Java/jcurses/lib TestJcurses
scala -cp /Users/pgiarrusso/software/Java/jcurses/lib/jcurses.jar:~/software/Java/jcurses/src:. -Djava.library.path=~/software/Java/jcurses/lib TestJcurses
As you can see, the ~ is there in the expanded version, and will arrive unchanged to your program, which will be unable to interpret it as anything since tilde expansion is a job for the shell.
Also, you shouldn't need the source directory ~/software/Java/jcurses/src in your classpath (since source files aren't needed to run the program). So try:
scala -cp ~/software/Java/jcurses/lib/jcurses.jar:. -Djava.library.path=$HOME/software/Java/jcurses/lib TestJcurses
I want to execute this command "dot -Tpng overview.dot > overview.png ", which is used to generate an image by Graphviz.
The code in scala:
Process(Seq("dot -Tpng overview.dot > overview.png"))
It does not work.
And I also want to open this image in scala. I work under Ubuntu. By default, images will be opened by image viewer. But I type "eog overview.png" in terminal, it reports error
** (eog:18371): WARNING **: The connection is closed
Thus, I do not know how to let scala open this image.
Thanks in advance.
You can't redirect stdout using > in command string. You should use #> and #| operators. See examples in process package documentation.
This writes test into test.txt:
import scala.sys.process._
import java.io.File
// use scala.bat instead of scala on Windows
val cmd = Seq("scala", "-e", """println(\"test\")""") #> new File("test.txt")
cmd.!
In your case:
val cmd = "dot -Tpng overview.dot" #> new File("overview.png")
cmd.!
Or just this (since dot accepts output file name as -ooutfile):
"dot -Tpng overview.dot -ooverview.png".!