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

时间:2019-01-31 02:02:59

标签: scala processbuilder

我有一个带有一系列定义步骤的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代码的替代方法?

3 个答案:

答案 0 :(得分:3)

根据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更改当前目录,也无法使用if,{{1}等bash语法},for

如果您真的想要bash等效代码,唯一的方法是使用bash运行脚本。

答案 1 :(得分:2)

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

import sys.process._

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

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

答案 2 :(得分:2)

我没有深入研究这个项目,因此我无法为您提供第一手示例,但请看一下Ammonite Scala project

从主页报价:

  

Ammonite允许您将Scala语言用于脚本编写目的:在REPL中,作为脚本,作为在现有项目中使用的库,或作为独立的系统外壳。

     

...

     

Ammonite的目标是使用轻量级的Ammonite运行时从重量级的“项目”中解放您的Scala代码:如果要运行某些Scala,请打开Ammonite-REPL并以交互方式运行它!如果要稍后运行,请将其保存到一些Scala脚本中并稍后运行。

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: