if (true=="shellbat") #;#\ : <<'HIDE_FROM_BASH_AND_SH' ::lindex tcl;# leading colons hide from .bat, trailing slash hides next line from tcl \ @call tclsh "%~dp0%~n0.bat" %* ::lindex tcl;#\ @set taskexitcode=%errorlevel% & goto :exit # -*- tcl -*- # ################################################################################################# # This is a tcl shellbat file # It is tuned to run when called as a batch file, a tcl script, an sh script or a bash script, # so the specific layout and characters used are quite sensitive to change. # It can be called on unix or windows platforms with or without the interpreter being specified on the commandline. # e.g ./filename.sh.bat in sh or bash or powershell # e.g filename.sh or filename.sh.bat at windows command prompt # e.g tclsh filename.sh.bat | sh filename.sh.bat | bash filename.sh.bat # In all cases an arbitrary number of arguments are accepted # To avoid the initial commandline on stdout when calling as a batch file on windows, use: # cmd /Q /c filename.sh.bat # (because we cannot use @if to silence it, as this isn't understood by tcl,sh or bash) # ################################################################################################# #fconfigure stdout -translation crlf # --- --- --- --- --- --- --- --- --- --- --- --- ---begin Tcl Payload #puts "script : [info script]" #puts "argcount : $::argc" #puts "argvalues: $::argv" # # --- --- --- --- --- --- --- --- --- --- --- --- --- # only exit if needed. see exitcode notes at bottom of file and exit there for consistency across invocation methods # --- --- --- --- --- --- --- --- --- --- --- --- ---end Tcl Payload #-- #-- bash/sh code follows. #-- protect from tcl using line continuation char on the previous comment for each line, like so: \ printf "etc" #-- or alternatively place sh/bash script within the false==false block #-- whilst being careful to balance braces {} #-- For more complex needs you should call out to external scripts #-- #-- END marker for hide_from_bash_and_sh\ HIDE_FROM_BASH_AND_SH #\ then #--------------------------------------------------------- if false==false # else { then : #--------------------------------------------------------- #-- leave as is if all that's required is launching the Tcl payload" #-- #-- Note that sh/bash script isn't called when running a .bat from cmd.exe on windows by default #-- adjust line 4: @call tclsh ... to something like @call sh ... @call bash .. or @call env sh ... etc as appropriate #-- if sh/bash scripting needs to run on windows too. #-- #printf "start of bash or sh code" #-- sh/bash launches Tcl here instead of shebang line at top #-- use exec to use exitcode (if any) directly from the tcl script exec /usr/bin/env tclsh "$0" "$@" #-- alternative - if sh/bash script required to run after the tcl call. #/usr/bin/env tclsh "$0" "$@" #tcl_exitcode=$? #echo "tcl_exitcode: ${tcl_exitcode}" #-- override exitcode example #exit 66 #printf "No need for trailing slashes for sh/bash code here\n" #--------------------------------------------------------- fi # } #--------------------------------------------------------- #-- comment for line sample 1 with trailing continuation slash \ #printf "tcl-invisible sh/bash line sample 1 \n" #-- comment for line sample 2 with trailing continuation slash \ #printf "tcl-invisible sh/bash line sample 2 \n" #-- Consistent exitcode from sh,bash,tclsh or cmd #-- Call exit in tcl (or sh/bash) code only if explicitly required, otherwise leave this commented out. #-- (script might be more widely useable without explicit exit. e.g in tcl: set ::argc 1; set ::argv "val"; source filename.sh.bat ) #-- exit line unprotected by trailing slash will work for tcl and/or sh/bash #exit 0 #exit 42 #--------------------------------------------------------- #-- end if true==shellbat on very first line\ fi #--------------------------------------------------------- #-- make sure sh/bash/tcl all skip over .bat style exit \ : <<'shell_end' #-- .bat exit with exitcode from tcl process \ :exit ::lindex tcl;#\ @exit /B %taskexitcode% #\ shell_end