3
votes

Comment convertir un script shell (bash) en code Scala?

J'ai un script shell avec une série d'étapes définies. J'essaye de convertir le script en code Scala en maintenant l'ordre des étapes. Fondamentalement, je veux que mon code Scala soit un miroir du script shell.

J'ai utilisé la bibliothèque sys.process._ . Le script shell a des commandes comme:

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>") ! 
  }
}

J'ai besoin de maintenir l'ordre d'exécution de ces étapes.

J'ai essayé quelque chose comme:

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

Je m'attends à ce que les opérations s'exécutent dans l'ordre où elles ont été définies. Je ne sais pas comment fonctionne ProcessBuilder / Process ou s'il existe une alternative pour convertir tout cela en code Scala?


1 commentaires

Ammonite se facture comme remplacement bash: ammonite.io/#Ammonite-Shell


3 Réponses :


3
votes

Selon le document , # | construit une commande qui exécutera la commande et redirigera la sortie vers l'autre. Cela étant dit, le code suivant dans Scala:

ls
echo hello

équivaut au code Bash suivant:

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

ce qui n'est pas ce que vous voulez.

Ce que vous recherchez est ### opérateur qui construit une commande qui exécutera une commande puis une autre. p >

En utilisant cet opérateur, vous pouvez écrire le code Scala suivant:

echo hello | wc -c

Ce qui équivaut au code Bash suivant:

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


1 commentaires

L'ammonite a une notion de dir de travail. ammonite.io/#Ammonite-Shell



2
votes

En plus de la méthode ### , comme @ymonad l'a souligné, vous devriez vraiment utiliser plus directement les méthodes ProcessBuilder . Cela rend le code plus facile à lire et à comprendre.

import sys.process._

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

L'utilisation d'une Seq [String] à la place d'une simple String offre quelques avantages lors de l'analyse de plusieurs arguments transmis au processus.


0 commentaires

2
votes

Je n'ai pas creusé dans ce projet, je ne peux donc pas vous aider avec un exemple de première main, mais jetez un œil au Projet Ammonite Scala .

Citation de la page d'accueil:

Ammonite vous permet d'utiliser le langage Scala à des fins de script: dans le REPL, en tant que scripts, en tant que bibliothèque à utiliser dans des projets existants ou en tant que shell système autonome.

...

Le but d'Ammonite est de libérer votre code Scala des "projets" lourds, en utilisant le runtime léger Ammonite: si vous voulez exécuter un peu de Scala, ouvrez l'Ammonite-REPL et exécutez-le, interactivement! Si vous souhaitez l'exécuter plus tard, enregistrez-le dans certains scripts Scala et exécutez-les plus tard.

Sur ce lien , vous trouverez quelques exemples de ce que vous pouvez faire:

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:


0 commentaires