Multiline shebang: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
(5 intermediate revisions by 4 users not shown)
Line 17:
{{trans|C}}
 
<langsyntaxhighlight Adalang="ada">#!/bin/bash
sed -n -e '7,$p' < "$0" > mulshbang.adb
gnatmake -q mulshbang
Line 33:
Ada.Command_Line.Argument(I));
end loop;
end Mulshbang;</langsyntaxhighlight>
 
{{out}}
Line 82:
The namespace = basename = filename minus the extension must be passed as a value to Clojure's -m flag.
 
<langsyntaxhighlight lang="clojure">":";exec clj -m `basename $0 .clj` $0 ${1+"$@"}</langsyntaxhighlight>
 
Alternate shebang, using the [https://github.com/kumarshantanu/lein-exec Leiningen 'exec' plugin]:
 
<langsyntaxhighlight lang="clojure">":";exec lein exec $0 ${1+"$@"}</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
Line 94:
Here, the script name is passed once to CLISP and once to ext:*args*, which normally omits it.
 
<langsyntaxhighlight lang="lisp">#!/bin/sh
#|
exec clisp -q -q $0 $0 ${1+"$@"}
|#</langsyntaxhighlight>
 
=={{header|E}}==
Line 105:
In this example, we are including the command name itself in the argument list, which would ordinarily not include it.
 
<langsyntaxhighlight lang="e">#!/bin/sh
>/dev/null; exec rune $0 $0 ${1+"$@"}
 
println(`I was called as ${interp.getArgs()[0]}.`)</langsyntaxhighlight>
 
=={{header|Emacs Lisp}}==
<langsyntaxhighlight lang="lisp">:;exec emacs -batch -l $0 -f main $*</langsyntaxhighlight>
 
=={{header|Erlang}}==
Line 117:
hello.erl
 
<langsyntaxhighlight Erlanglang="erlang">#!/usr/bin/env escript
 
-module(hello).
-export([main/1]).
 
main(_) -> io:format("Hello World!~n", []).</langsyntaxhighlight>
 
This works fine when the module is run by itself with dot slash:
 
<langsyntaxhighlight lang="sh">$ ./hello.erl
Hello World!</langsyntaxhighlight>
 
But when another Erlang module tries to import the code, or you try to compile manually in erl, you get a syntax error.
 
<langsyntaxhighlight lang="sh">$ erl
Erlang R14B03 (erts-5.8.4) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
 
Line 138:
./hello.erl:1: syntax error before: '#'
./hello.erl:4: no module definition
error</langsyntaxhighlight>
 
=={{header|F Sharp|F#}}==
Line 144:
F# scripts may be run with dot-slash notation using the following multiline shebang:
 
<langsyntaxhighlight lang="f#">#light (*
exec fsharpi --exec "$0" --quiet
*)
 
let main = printfn "Hello World"</langsyntaxhighlight>
 
However, if a script has any dependencies that need to be compiled in, the fsharpi interpreter will not understand how to import them. This means dot-slashing is no longer viable, and the script must be compiled in order to run properly. The shebang can stay, but it is best to remove it, to make clear to users that the script should not be dot-slashed.
Line 155:
Factor no longer requires a space after <code>#!</code> as of v0.95.
 
<langsyntaxhighlight lang="factor">#!/usr/bin/env factor -script</langsyntaxhighlight>
 
=={{header|Forth|Gforth}}==
We can use Gforth's (non-ANS standard) support for shebangs and the '#' number prefix to make Gforth skip over the shebang without interfering with shell script interpretation.
 
<langsyntaxhighlight lang="forth">#! /bin/sh
#0 [IF] \ lines below read by shell but ignored by Gforth
exec gforth \
Line 168:
[THEN]
.( hello world) CR BYE
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
FreeBASIC is a compiled, uninterpreted language, so it cannot be run directly from the Unix command line with a shebang.
 
However, you can create a shell script that compiles and runs your FreeBASIC program. Here I show an example:
 
<syntaxhighlight lang="vbnet">
<lang Phix>#!/bin/bash
# Compile the FreeBASIC program
fbc myprogram.bas
# Run the compiled program
./myprogram
</syntaxhighlight>
 
In this script, myprogram.bas is a FreeBASIC program. When you run this shell script, it will compile the FreeBASIC program and then run it.
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">#!/bin/bash
sed -n -e '12,$p' < "$0" > ttmmpp.go
go build ttmmpp.go
Line 197 ⟶ 212:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">#!/bin/bash
script_dir="$(cd $(dirname $0) >/dev/null; pwd -P)"
 
Line 213 ⟶ 228:
!#
println 'aoeu'
</syntaxhighlight>
</lang>
 
=={{header|Haskell}}==
Line 219 ⟶ 234:
{{trans|C}}
 
<langsyntaxhighlight Haskelllang="haskell">#!/bin/bash
sed -n -e '7,$p' < "$0" > $0.$$.hs
ghc $0.$$.hs > /dev/null
Line 229 ⟶ 244:
 
main :: IO ()
main = getArgs >>= mapM_ (uncurry $ printf "argv[%d] -> %s\n") . zip ([0..] :: [Int])</langsyntaxhighlight>
 
{{out}}
Line 242 ⟶ 257:
Or you can 'cheat' by ignoring Bash's complaints about Haskell comments (gives the exact same output as above):
 
<langsyntaxhighlight Haskelllang="haskell">#!/bin/bash
{- 2> /dev/null
exec runghc $0 $0 $@
Line 250 ⟶ 265:
 
main :: IO ()
main = getArgs >>= mapM_ (uncurry $ printf "argv[%d] -> %s\n") . zip ([0..] :: [Int])</langsyntaxhighlight>
 
=={{header|J}}==
Line 256 ⟶ 271:
Assuming this task is asking for a mix of unix shell commands and J, and also that the J binary directory is listed in <code>$PATH</code>
 
<langsyntaxhighlight Jlang="j">#!/bin/sh
# 0 :0
echo unix shell commands go here
Line 282 ⟶ 297:
echo p:i. 3 4
exit 0
</syntaxhighlight>
</lang>
 
'''Notes:'''
Line 300 ⟶ 315:
Here's a variant where the shell script tests J's exit code and does something different based on success or failure.
 
<langsyntaxhighlight Jlang="j">#!/bin/sh
# 0 :0
echo unix shell commands go here
Line 325 ⟶ 340:
echo p:i. 3 4
exit 0
</syntaxhighlight>
</lang>
 
The <code>exit $?</code> line tells the shell interpreter to ignore the J part of the file, and the <code>$?</code> reuses J's exit code as the exit code from the shell instance.
 
Note that we've left off the onfail handler within J, and just used a minimal definition to give us a non-zero exit code for the error case. Mostly, the assumption here would be that the error message would not be interesting, and that any failure should be handled by a retry. But you could replace the exit on error line here with the full definition and <code>9!:</code> preparatory bit from the previous example and you could also of course change the <code>1!:2&2</code> lines (<code>1!:2&2</code> is the "low-level" write to stdout mechanism for J - and, yes, those numbers are part of the definition of the language - or at least the "Foreigns" part of the language - note that ultimately all computer languages resolve to things which can be thought of as numbers or sequences of numbers, though some people will vigorously assert other things).
 
=={{header|jq}}==
 
Here is an example using bash:
<pre>
#!/bin/bash
# this line is ignored by jq provided it ends with a backslash \
exec jq -nef "$0" "$@"
# jq code follows
true
</langpre>
 
Notice the trailing `\` at the end of the second line.
 
Arguments can be passed in to the script, e.g. using the --arg NAME VALUE option.
 
The above script will also work with `sh` provided the quotation marks around `$@` are removed.
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">
#!/bin/sh
#=
Line 355 ⟶ 387:
 
@time countto(10^10)
</syntaxhighlight>
</lang>
 
=={{header|MATLAB}}==
Line 363 ⟶ 395:
~/bin/shmatlab%:
 
<langsyntaxhighlight lang="bash">#!/bin/sh
matlab -nojvm -nodisplay -nosplash -r "varargin = regexp('${1+"$@"}', ' ', 'split'); nvarargin = length(varargin); run('$1'); exit" | tail -n +16
</syntaxhighlight>
</lang>
 
args.m:
 
<langsyntaxhighlight lang="matlab">'shmatlab'% $0 ${1+"$@"}
'exit';
 
for i = 1:nvarargin
disp(varargin{i});
end</langsyntaxhighlight>
 
Example:
Line 389 ⟶ 421:
In Nim, multiline comments start with <code>#[</code> and end with <code>]#</code>. This allows to build a polyglot program which can be run as a shell script and compiled as a Nim program.
 
<langsyntaxhighlight Nimlang="nim">#!/bin/bash
#[
echo Put here code to run as a shell script.
Line 396 ⟶ 428:
 
# Nim program
echo "Executing Nim program"</langsyntaxhighlight>
 
=={{header|OCaml}}==
Line 402 ⟶ 434:
ocamlc hates shebangs, so much trickery is needed. The number of underscores in the dummy kkkk identifier corresponds to the number of bash strings in the shebang. Thus, core library .cma files can be specified this way in interpreted mode, though accessing other OCaml scripts requires compiling them first, and referencing the .cmo's here.
 
<langsyntaxhighlight lang="ocaml">if true then ignore begin let kkkk _ _ _ _ = 0 in kkkk
"exec" "ocaml" "$0" "$@" + let fi = 0 and exit _ _ = 0 in if false
then exit
Line 409 ⟶ 441:
end;;
 
let main = print_endline "Hello World!"</langsyntaxhighlight>
 
Example:
Line 431 ⟶ 463:
=={{header|PARI/GP}}==
The PARI equivalent to a multiline shebang is a collection of <code>GP;</code> lines:
<syntaxhighlight lang="c">/*
<lang C>/*
GP;install("C_function_name","G","GP_name","./filename.gp.so");
GP;addhelp(GP_name, "GP_name(n): Computes the foo of bar(n).");
*/</langsyntaxhighlight>
These commands are passed to GP when invoked by gp2c.
 
=={{header|Perl}}==
From <code>perldoc perlrun</code>, the following is supposed to find perl one way or another under sh, csh or perl.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
eval '(exit $?0)' && eval 'exec perl -wS $0 ${1+"$@"}'
& eval 'exec /usr/bin/perl -wS $0 $argv:q'
if $running_under_some_shell;</langsyntaxhighlight>
 
=={{header|Phix}}==
Obviously this is not pwa/p2js compatible, since you cannot run bash or sed (with redirection) or phix or 'rm tmp.eu' from within a browser, and is only intended to be run on Linux, though you could perhaps run it on Windows but only in some kind of bash shell.
<lang Phix>#!/bin/bash
<!--<syntaxhighlight lang="phix">-->
sed -n -e '7,$p' < "$0" > tmp.eu
<span style="color: #000000;">#!/bin/bash
\path\to\phix tmp.eu "$@"
sed -n -e '7,$p' < "$0" > tmp.eu
STATUS=$?
rm \path\to\phix tmp.eu "$@"
exit $ STATUS=$?
rm tmp.eu
?command_line()</lang>
exit $STATUS</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (not that pwa/p2js would get this far!)</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
Alternatively it was not particularly difficult, just for this task, to add #[ and #] handling, just like /* and */, to both desktop/Phix and pwa/p2js.<br>
Note that I simply cannot see how #! ... !# could ever work, in any programming language, that is while also allowing single line shebangs with no closing !#.<br>
Hence the following (partly based on the Julia entry) now (1.0.2) also works fine, with no detrimental (or beneficial) effect either on (standard) Windows or under pwa/p2js:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #00000;font-style:italic;">#!/bin/bash
#[
echo Phix ignores all text between #[ and #] in exactly the same way as /* and */
echo (both "and" are nested comments), allowing arbitrary shell code, for example
cd /user/project/working
\ exec /path\/to\/phix tmp.eu"$0" "$@"
exit # may be needed for the shell to ignore the rest of this file.
# comments ingored by Phix end here -&gt; #]</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"This is Phix code\n"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
We can use a multi-line comment #{ ... }# to hide the shell commands from Lisp. The opening #{ in turn is a coment for the shell.
<langsyntaxhighlight PicoLisplang="picolisp">#!/bin/bash
#{
exec pil $0 foo bar
Line 462 ⟶ 513:
# Lisp code
(println (cadr (file)) (opt) (opt))
(bye)</langsyntaxhighlight>
{{out}}
<pre>$ ./myScript
Line 469 ⟶ 520:
=={{header|Pike}}==
we use a multiline comment to hide the shell command from pike, and we can use a preprocessor directive to hide the comment begin from the shell.
<langsyntaxhighlight Pikelang="pike">#!/bin/bash
#define foo foo /*
exec pike $0 hello world
Line 477 ⟶ 528:
{
write("%O\n", argv);
}</langsyntaxhighlight>
 
{{out}}
Line 490 ⟶ 541:
This style of shebang would also work with other languages that use double dashes for comments, though most of them (Lua, Haskell) already support traditional #!... shebangs.
 
<langsyntaxhighlight lang="postgresql">--() { :; }; exec psql -f "$0"
 
SELECT 'Hello World!';</langsyntaxhighlight>
 
=={{header|Python}}==
We can use multiple strings to make the shell commands do nothing from Python (actually they become the module docstring.).
<langsyntaxhighlight Pythonlang="python">#!/bin/bash
"exec" "python" "$0"
 
print "Hello World"</langsyntaxhighlight>
{{out}}
<pre>$ ./myScript
Line 506 ⟶ 557:
Control structures (if/for/etc.) can't be quoted,
but one can use the following to embed any script:
<langsyntaxhighlight Pythonlang="python">#!/bin/sh
"true" '''\'
if [ -L $0 ]; then
Line 516 ⟶ 567:
__doc__ = """module docstring"""
 
print "Hello World"</langsyntaxhighlight>
 
Here we use a) the code <nowiki>'''\'</nowiki> translates to \ in shell, but opens a multi-line string in Python; b) the true command ignores its argument, c) we always exit before the ending <nowiki>'''</nowiki> so that the shell interpreter never reads it. Also, remember to set any docstrings by assigning to __doc__ since the docstring is already used for the shell script.
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#!/bin/sh
#| -*- scheme -*-
Line 535 ⟶ 586:
(printf "argument: ~a\nexecuted as: ~a\n"
arg (find-system-path 'exec-file)))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
 
<syntaxhighlight lang="raku" perl6line>#!/usr/local/bin/raku
use MONKEY; EVAL '(exit $?0)' && EVAL 'exec rake $0 ${1+"$@"}'
& EVAL 'exec raku $0 $argv:q'
if 0;</langsyntaxhighlight>
 
=={{header|Ruby}}==
Line 552 ⟶ 603:
This script works both ways: either <code>/bin/sh script.rb</code> or <code>ruby script.rb</code> would run multiple lines of shell commands, and then start Ruby.
 
<langsyntaxhighlight lang="ruby">#!/bin/sh
 
# Insert shell code here!
Line 574 ⟶ 625:
ARGV.each_with_index do |arg, i|
puts " ARGV[#{i}]: #{arg}"
end</langsyntaxhighlight>
 
When running <code>/bin/sh scratch.rb</code>, the shell:
Line 594 ⟶ 645:
The scalac compiler does not.
 
<langsyntaxhighlight lang="scala">
#!/bin/bash
FOO=bar
Line 610 ⟶ 661:
}
 
println("fact(5) = " + fact(5));</langsyntaxhighlight>
 
=={{header|Scheme}}==
{{works with|Chicken Scheme}}
 
<langsyntaxhighlight lang="scheme">#!/usr/bin/env csi -ss</langsyntaxhighlight>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">#!/bin/sh
 
#`(if running under some shell) {
Line 624 ⟶ 675:
}
 
say "Hello, #{ARGV[0]}!"</langsyntaxhighlight>
 
{{out}}
Line 639 ⟶ 690:
 
=={{header|Smalltalk}}==
<langsyntaxhighlight lang="smalltalk">"exec" "gst" "-f" "$0" "$0" "$@"</langsyntaxhighlight>
 
=={{header|SQL PL}}==
Line 645 ⟶ 696:
Based on the Postgres shebang, it works the same with IBM Db2.
 
<langsyntaxhighlight lang="sql pl">
--() { :; }; exec db2 -txf "$0"
 
Line 652 ⟶ 703:
select 'Hello' from sysibm.sysdummy1;
values current date;
</syntaxhighlight>
</lang>
Output:
<pre>
Line 679 ⟶ 730:
=={{header|Tcl}}==
It is normal to use a line like this:
<syntaxhighlight lang ="tcl">#!/usr/bin/env tclsh</langsyntaxhighlight>
But in cases where that is not enough perhaps because it needs some logic to locate the Tcl interpreter to use the differences in the way Tcl and the Bourne shell interpret end-of-line backslashes in comments can be used:
<langsyntaxhighlight lang="tcl">#!/bin/sh
# Next line is comment in Tcl, but not in sh... \
exec tclsh "$0" ${1+"$@"}</langsyntaxhighlight>
Additional complexity can be added so long as the lines for the shell are commented in a Tcl sense.
 
Line 713 ⟶ 764:
 
You can get around this by placing shell commands in a block comment after a single line shebang. So (ignoring the strange error message) the following works:
<langsyntaxhighlight ecmascriptlang="wren">#!/bin/bash
/*
echo "Hello from bash"
/bin/wren multiline_shebangMultiline_shebang.wren
exit
*/
System.print("Hello from Wren")</langsyntaxhighlight>
 
{{out}}
<pre>
$ chmod +x multiline_shebangMultiline_shebang.wren
$ ./multiline_shebangMultiline_shebang.wren
./multiline_shebangMultiline_shebang.wren: line 2: /bin: Is a directory
Hello from bash
Hello from Wren
Line 731 ⟶ 782:
<br>
However, we don't actually need a multiline shebang to get the script name as this is always passed automatically as the second command line argument when the Wren process is spawned, the first argument being the Wren executable itself. Moreover, if a single line shebang is used, the third argument will be the shell command used to execute the script.
<langsyntaxhighlight ecmascriptlang="wren">#!/bin/wren multiline_shebangMultiline_shebang_2.wren
import "os" for Process
 
Line 740 ⟶ 791:
if (args.count > 3) {
for (i in 3...args.count) System.print("Argument %(i-2) : %(args[i])")
}</langsyntaxhighlight>
 
{{out}}
<pre>
$ chmod +x Multiline_shebang_2.wren
$ ./multiline_shebangMultiline_shebang_2.wren one two three
Executable : /bin/wren
Script name : multiline_shebangMultiline_shebang_2.wren
Shell command : ./multiline_shebangMultiline_shebang_2.wren
Argument 1 : one
Argument 2 : two
Line 757 ⟶ 809:
 
File foo.zkl (the .zkl extension is needed):
<langsyntaxhighlight lang="zkl">#!/bin/sh
#<<<#
echo "A shell script in a zkl program ($0)"
Line 764 ⟶ 816:
exit
#<<<#
println("The shell script says ",vm.arglist.concat(" "));</langsyntaxhighlight>
{{out}}
<pre>
2,122

edits