以下脚本将打印它的文件系统路径。连续尝试三种不同的方法,直到其中一种成功。
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"))