The following script will print it's filesystem path. Three different approaches are tried in succession, until one of them succeeds.
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
}
}
}
}
The easiest and most portable is the 2nd approach, which depends on use of a wrapper script, as in the following example, for defining Property 'scala.script.name' before calling $SCALA_HOME/bin/scala. The wrapper script needs to be in your PATH ahead of $SCALA_HOME/bin, of course. The result is more bulletproof, but is only applicable to scripts.
#!/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 "$@"
Use of this wrapper around the scala launcher simplifies usage to the following:
#!/usr/bin/env scala
!#
printf("%s\n",System.getProperty("scala.script.name"))