4

我正在寻找一种方法来使用由执行的 *.scala 文件的完整路径

scala /path/to/file/file.scala 

原因是在我的脚本中,我想使用相对于 file.scala 保存位置的路径。所以,假设我想在调用 file.scala 时从 file.scala 内部调用 /path/to/file/file_second.scala

scala ./to./file/file.scala 

因为我从中调用 scala 的目录是 /path (即 System.getProperty("user.dir") 将返回的内容)。我所知道的先验是 file_second.scala 与 file.scala 位于同一目录中,但实际上并不知道完整路径。

我努力了。其中包括 getClass.getResource("").split(":")(1),但这将返回 /path/./ 或 /tmp/scala.tmp/

我想必须有一个干净的解决方案,因为 scala -savecompiled 将在我想要处理的那个目录中创建一个 *.jar,但我只是不知道如何......:/

非常感谢您的帮助。

4

4 回答 4

7

脚本序言:

#!/bin/sh
export SCRIPT_PATH=$(readlink -f "$0") && exec scala "$0" "$@"
!#

读取值:

val scriptPath = System.getenv("SCRIPT_PATH")
于 2013-06-26T19:22:13.813 回答
1

I've done this in the past in Java. It's not pretty, and it may not be 100% reliable depending on the details of your class loader situation.

Here is some Scala code that prints out the location of its own class file.

import java.net.URL

object LocationTest extends App {
  val classDirURL = LocationTest.getClass.getResource("LocationTest.class")
  val classDirPath = classDirURL.getPath.replaceAll("%20", " ")
  println(classDirPath)
}

prints

/Users/connor/desktop/LocationTest.class
于 2012-04-05T02:33:56.410 回答
0

您可以使用参数调用您的程序:

scala -DPARAM_DIR=tmp Foo

并检查程序中的参数:

object Foo extends App {
  val dir = System.getProperty ("PARAM_DIR")
  println ("Dir: " + dir) 
}

所以这不会(必然)使用 Foo.scala 所在的同一个目录,但它会很灵活,并且可以在运行时被告知在哪里寻找一个类。

在正常情况下,您可以将类捆绑在 Jar 中,或者设置一个公共类路径,然后您可能会拥有一个相对于类路径解析的包:

对于一个类 to.file.File 中

 /path/to/file/file.scala 

它将是类路径/path,对于包中的类文件,file它将是/path/to/。

如果您的类路径是 /path/to/file,那么第二个类应该可以通过名称访问。

于 2012-04-05T00:20:44.117 回答
0

以下脚本将打印它的文件系统路径。连续尝试三种不同的方法,直到其中一种成功。

import java.io.File

printf("[%s]\n",new File(getScriptName).getCanonicalPath)
System.exit(0)

def getScriptName:String = {
  // this approach works on the sun jvm:
  val jcmd = System.getProperty("sun.java.command","")
  jcmd.split("""\s+""").toList.reverse.head match {
  case name if new File(name).exists => name
  case _ =>
    // for this to work, you need to set -Dscala.script.name at script launch
    System.getProperty("scala.script.name","") match {
    case name if new File(name).exists => name
    case _ =>
      // last resort: derive script basename from stackdump
      val basename = {
        val filenames = new RuntimeException("").getStackTrace.map { it
          => it.getFileName
        }
        filenames.indexOf("NativeMethodAccessorImpl.java") match {
          case -1 =>  filenames.reverse.head
          case num => filenames(num - 1)
        }
      }
      // then search the system PATH for the script file
      import scala.collection.JavaConversions._
      val sep = System.getProperty("path.separator")
      val path = System.getenv("PATH").split(sep)
      path.map(new File(_,basename)).find( _.exists ) match {
        case Some(scriptfile) => scriptfile.getCanonicalPath
        case _ => basename // better than nothing
      }
    }
  }
}

最简单和最可移植的是第二种方法,它依赖于使用包装脚本,如下例所示,用于在调用 $SCALA_HOME/bin/scala 之前定义属性“scala.script.name”。当然,包装脚本需要位于 $SCALA_HOME/bin 之前的 PATH 中。结果更加防弹,但仅适用于脚本。

#!/usr/bin/env sh
for SCRIPT_NAME; do true ; done # set SCRIPT_NAME to the last argument
JAVA_OPTS="$JAVA_OPTS -Dscala.script.name=${SCRIPT_NAME}"
$SCALA_HOME/bin/scala "$@"

在 scala 启动器周围使用此包装器可将使用简化为以下内容:

#!/usr/bin/env scala
!#
printf("%s\n",System.getProperty("scala.script.name"))
于 2012-04-24T18:30:08.027 回答