次のスクリプトは、そのファイルシステムパスを出力します。そのうちの1つが成功するまで、3つの異なるアプローチが連続して試行されます。
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
}
}
}
}
最も簡単で移植性の高い方法は2番目のアプローチです。これは、次の例のように、$ 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 "$@"
スカラランチャーの周りにこのラッパーを使用すると、次のように使用が簡単になります。
#!/usr/bin/env scala
!#
printf("%s\n",System.getProperty("scala.script.name"))