Scala как оболочка script: банки на пути к классам

Вы можете запустить scala script как оболочку linux script:

#!/bin/sh
exec scala "$0" "[email protected]"
!#

println("Hello")

В одном из таких script мне нужно загрузить классы из группы jars (которые находятся в том же каталоге, что и script). Если бы это был REPL, я мог бы использовать :jar, но недоступный в режиме script.

Я пытаюсь установить параметр -classpath:

#!/bin/sh
exec scala -classpath '.:./*.jar' "$0" "[email protected]"
!#

import javax.media.jai.{JAI, RenderedOp}

но компилятор просто не может найти классы:

error: object media is not a member of package javax
import javax.media.jai.{JAI, RenderedOp}
             ^

Как включить эти банки?

Ответы

Ответ 1

По какой-то причине glob (*.jar) не работал. Мне удалось запустить script, поместив все библиотеки вручную:

#!/bin/sh
exec scala -cp lib/jai_codec.jar:lib/jai_core.jar:lib/mlibwrapper_jai.jar $0 [email protected]
!#

import javax.media.jai.{JAI, RenderedOp}

Я не знаю, почему glob не работает.

Обратите внимание, что в этом случае у меня нет . в пути к классам, потому что сам script предоставляется в качестве аргумента. Во многих случаях, хотя вам нужно будет включить его:

exec scala -cp .:lib/jai_codec.jar:lib/jai_core.jar:lib/mlibwrapper_jai.jar $0 [email protected]

Основываясь на этом полезном сообщении, у меня есть заголовок script, который тянет каждую банку в папке lib, даже если script (или его папка) являются символическими ссылками.

#!/bin/sh
L=`readlink -f $0`
L=`dirname $L`/lib
cp=`echo $L/*.jar|sed 's/ /:/g'`
/usr/bin/env scala -classpath $cp $0 [email protected]
exit
!#
  • Первая строка превращает данное script местоположение $0 в его фактическое местоположение на диске, расширяя символические ссылки.
  • Вторая строка удаляет имя script и добавляет /lib
  • Третья строка создает переменную cp со всеми банками, разделенными :
  • Четвертая строка работает scala, где бы она ни была.
  • Пятая строка завершается. Возможно, это не обязательно, но мне становится легче.

Ответ 2

exec scala -classpath ./*.jar $0 [email protected]

будет работать

Ответ 3

Я рекомендую вам использовать SBT вместо этого. См. скрипты wiki, в котором объясняется, как сделать что-то вроде этого:

#!/usr/bin/env scalas
!#

/***
scalaVersion := "2.9.0-1"

libraryDependencies ++= Seq(
  "net.databinder" %% "dispatch-twitter" % "0.8.3",
  "net.databinder" %% "dispatch-http" % "0.8.3"
)
*/

import dispatch.{ json, Http, Request }
import dispatch.twitter.Search
import json.{ Js, JsObject }

def process(param: JsObject) = {
  val Search.text(txt)        = param
  val Search.from_user(usr)   = param
  val Search.created_at(time) = param

  "(" + time + ")" + usr + ": " + txt
}

Http.x((Search("#scala") lang "en") ~> (_ map process foreach println))

Ответ 4

http://www.scalaclass.com/node/10 Это должно сработать для вас. Я просто фиксирую зависимость в соответствии с ней.

Ответ 5

Вы также можете поместить одинарные кавычки вокруг пути к классам с помощью glob, например:

exec scala -classpath '.:*.jar' "$0" "[email protected]"

Ответ 6

Чтобы избежать определения определения пути к классам в каждом заголовке, вы можете определить функцию, которая обертывает ваш исполняемый файл scala в (например) ваш .bashrc и делает его видимым для внешней области:

...
function scala() {

    PARAMS=( "[email protected]" )

    FILENAME=${PARAMS[0]}
    REMAINING_PARAMS=(${PARAMS[@]:1:${#PARAMS[@]}})

    CUSTOM_CLASSPATH_DEF=".:/whatever/*"
    /path/to/scala -cp "$CUSTOM_CLASSPATH_DEF" -Dscala.color=true "$FILENAME" "${REMAINING_PARAMS[@]}"
}

export -f scala 
...

Теперь вы можете определить свой заголовок как:

#!/bin/bash
scala "$0" "[email protected]"
exit 0
!#

(Вы все еще можете использовать REPL, набрав 'scala' из командной строки)