如何将 shell 脚本 (bash) 转换为 Scala 代码?

How to convert a shell script (bash) to Scala code?

我有一个 shell 脚本,其中包含一系列已定义的步骤。我试图通过维护步骤的顺序将脚本转换为 Scala 代码。基本上我希望我的 Scala 代码成为 shell 脚本的镜像。

我用过 sys.process._ 库。 shell 脚本包含如下命令:

mkdir <pathToDir>
hadoop fs -copyToLocal <source> <dest>
rm -r <pathToDir>
java -jar <someScript>

我需要保持这些步骤的执行顺序。

我试过类似的东西:

import sys.process._
Class A {
  def processMethod(): Unit = { 
    Process("mkdir -p <dir1>") #| Process("hadoop fs -copyToLocal 
    <hdfsDir1> <localDir1>") #| Process("mkdir -p <dir2>") #| 
    Process("hadoop fs -copyToLocal <hdfsdir2>/*.parquet <localDir2>") 
    #| Process("java -jar <pathToJarFile> -script <sampleScripts> 1>&2") 
    #| Process("rm -r<localDir1>") #| Process("rm -r <localDir2>") ! 
  }
}

我希望操作按照定义的顺序执行。我对 ProcessBuilder/Process 的工作方式感到困惑,或者是否有其他方法可以将整个东西转换为 Scala 代码?

根据document#|构造一个命令,将运行命令并将输出通过管道传递给其他人。 也就是说,Scala 中的以下代码:

(Process("echo hello") #| Process("wc -c")).!

等同于下面的Bash代码:

echo hello | wc -c

这不是你想要的。

您正在寻找的是 ### 运算符,它构造一个命令,该命令将 运行 一个命令然后另一个。

使用此运算符,您可以编写以下 Scala 代码:

(Process("ls") ### Process("echo hello")).!

相当于以下 Bash 代码:

ls
echo hello

但是,请注意,以上述方式使用 Process 并不完全等同于 bash,因为它不能使用 cd 更改当前目录,也不能使用 bash 语法,例如if, for, case.

如果你真的想要 bash 等效代码,唯一的方法是 运行 将脚本与 bash 结合起来。

除了 ### 方法之外,正如@ymonad 指出的那样,您真的应该更直接地使用 ProcessBuilder 方法。它使代码更易于阅读和理解。

import sys.process._

Seq("mkdir", "SO")        ###
Seq("touch", "SO/file")   ###
Seq("mv", "SO", "SoWhat") !

在解析传递给进程的多个参数时,使用 Seq[String] 代替简单的 String 提供

我没有深入研究这个项目,所以我无法通过第一手示例帮助您,但请看一下 Ammonite Scala project

引用自主页:

Ammonite lets you use the Scala language for scripting purposes: in the REPL, as scripts, as a library to use in existing projects, or as a standalone systems shell.

...

The goal of Ammonite is to liberate your Scala code from heavyweight "projects", using the lightweight Ammonite runtime: if you want to run some Scala, open the Ammonite-REPL and run it, interactively! If you want to run it later, save it into some Scala Scripts and run those later.

At this link 是您可以执行的操作的一些示例:

import ammonite.ops._

// Let's pick our working directory
val wd: Path = pwd/'ops/'target/"scala-2.11"/"test-classes"/'example3

// And make sure it's empty
rm! wd
mkdir! wd

// You can create folders through `mkdir!`. This behaves the same as
// `mkdir -p` in Bash, and creates and parents necessary
val deep = wd/'this/'is/'very/'deep
mkdir! deep

// You can also use backticks to execute commands which aren't valid Scala identifiers, e.g.
`ssh-add`
Enter passphrase for /Users/haoyi/.ssh/id_rsa: