Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shebang "#!" starts and "!#" ends?

I have been using shebang #! for a while and today came across a use case that confuses me.

There are several ways to run scala script like

#!/usr/bin/env scala 
println("hello world")

However, I came across this version of shebang

#!/bin/sh
exec scala "$0" "$@"
!#
println("hello world")

Looks like this solution basically invokes the bash first, the run exec scala "$0" "$@" where $0 denotes the current file name and $@ is input arguments in a positional array.

My question is does that mean everything between #! and !# could be executed in bash,

#!/bin/sh
exec scala "$0" "$@"
echo "oh Yeah"
!#
println("hello world")

It did not error out but neither gave me the "oh Yeah" in the stdout, can anyone explain to me what is going on here?


update: after realizing !# is a scala thing, I downloaded the source code of scala and realized it only appears in the comment of ScriptRunner.scala part written by Lex Spoon.

like image 735
B.Mr.W. Avatar asked Oct 29 '15 19:10

B.Mr.W.


People also ask

What is shebang slang for?

The informal phrase"the whole shebang" means "everything," which you could also call "the whole ball of wax" or "the whole enchilada." Shebang is an American word, first used by Civil War soldiers (and the poet Walt Whitman) to mean "rustic dwelling" or "hut." In 1872, Mark Twain used shebang to mean "vehicle," but ...

Where did the term shebang originate?

Etymology 1 In the sense of “temporary shelter”, it was perhaps brought by US Civil War Confederate enlistees from Louisiana, from French chabane (“hut, cabin”), a dialectal form of French cabane (“a covered hut, lodge, cabin”) (see cabin, cabana).

Should I use shebang?

The most common need for using shebang appears when we're writing shell scripts. “/bin/sh” is actually the symlink to an sh-compatible implementation of sh (Shell Command Language). In most cases, it'll be bash (Bourne-Again SHell), but if we want to secure portability, we should use the symlink.


1 Answers

The !# line has no meaning to the shell.

The #!/bin/sh line means that the script is executed by /bin/sh. The exec scala "$0" "$@" line invokes scala, passing the name of the script and its arguments to the scala command. Since exec doesn't return, the shell doesn't see the rest of the script.

I don't know Scala, but my educated guess is that the Scala interpreter itself treats everything from the #! line to the !# line as a comment. It then starts executing with the Scala statement println("hello world").

In short the !# is Scala syntax, not shell syntax (but the Scala syntax is designed to let it be used like this in a shell script).

In a quick look at the Scala Language Specification, I haven't found out how this is defined. It's mentioned, but not explained, in this question. It's likely, as chepner 3's comment suggests, that it's a hack in the Scala interpreter rather than part of the actual language syntax.

som-snytt found the code in the Scala interpreter that implements this here:

object ScriptSourceFile {
  /** Length of the script header from the given content, if there is one.
   *  The header begins with "#!" or "::#!" and ends with a line starting
   *  with "!#" or "::!#".
   */
...

But I wonder whether it's documented.

like image 130
Keith Thompson Avatar answered Oct 21 '22 01:10

Keith Thompson