Use shebang/hashbang in Windows Command Prompt
Asked Answered
P

6

39

I'm currently using the serve script to serve up directories with Node.js on Windows 7. It works well in the MSYS shell or using sh, as I've put node.exe and the serve script in my ~/bin (which is on my PATH), and typing just "serve" works because of it's Shebang (#!) directive which tells the shell to run it with node.

However, Windows Command Prompt doesn't seem to support normal files without a *.bat or *.exe extension, nor the shebang directive. Are there any registry keys or other hacks that I can get to force this behavior out of the built-in cmd.exe?

I know I could just write up a simple batch file to run it with node, but I was wondering if it could be done in a built-in fasion so I don't have to write a script for every script like this?

Update: Actually, I was thinking, is it possible to write a default handler for all 'files not found' etc. that I could automatically try executing within sh -c?

Thanks.

Psychologist answered 25/7, 2011 at 14:55 Comment(1)
Have you considered coming back to update the accepted answer? The one you accepted is incorrect, and you have a very good alternative just below it.Tantalic
P
55

Yes, this is possible using the PATHEXT environment variable. Which is e.g. also used to register .vbs or .wsh scripts to be run "directly".

First you need to extend the PATHEXT variable to contain the extension of that serve script (in the following I assume that extension is .foo as I don't know Node.js)

The default values are something like this:

PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

You need to change it (through the Control Panel) to look like this:

PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.FOO

Using the control panel (Control Panel -> System -> Advanced System Settings -> Environment Variables is necessary to persist the value of the PATHEXT variable.

Then you need to register the correct "interpreter" with that extension using the commands FTYPE and ASSOC:

ASSOC .foo=FooScript
FTYPE FooScript=foorunner.exe %1 %*

(The above example is shamelessly taken from the help provided by ftype /?.)

ASSOC and FTYPE will write directly into the registry, so you will need an administrative account to run them.

Palatial answered 25/7, 2011 at 15:13 Comment(8)
That's not the same as a shebang. A shebang works for any file; this only works for particular file extensions. Completely different concept.Laski
But it will allow the user to run the file without any further ado.Palatial
@Mehrdad this is basically the "Windows equivalent" of shebang.Clemence
Quicker PATHEXT setting from elevated command-line: setx PATHEXT "%PATHEXT%;.FOO" -mLaurilaurianne
I learned a lot from this post. It reminds me of this batch script I wrote that associates .jar files with java.exe : gist.github.com/djangofan/4144970Ephraimite
While this works perfect it drives the shebang line within the files ad absurdum - maybe, under windows, it is better to forget about the use of shebang altogether and work (as described above) completely with custom file extensions instead ?! (That is my lesson learned at least)Everhart
@petermeissner: Windows does not support a shebang line at all. This is the closest you can get in Windows. The result is the same: you can run a script file without specifying the interpreter.Palatial
I suspected that much - thanks for the making this point clear once more.Everhart
G
4

Command prompt does not support shebang , however there are a lot hybrid techniques for different languages that you allow to combine batch and other languages syntax in one file.As your question concerns node.js here's a batch-node.js hybrid (save it with .bat or .cmd extension):

0</* :{
        @echo off
        node %~f0 %*
        exit /b %errorlevel%
:} */0;


console.log(" ---Self called node.js script--- ");

console.log('Press any key to exit');
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));

It is possible to be done with many other languages like Ruby,Perl,Python,PHP and etc.

Giron answered 22/2, 2018 at 14:41 Comment(6)
Wow! That really works well. The best solution IMO as it requires no changes to the system and works for all interpreters.Heathenish
That is a clever hack. Do you have a reference/link for how this can be done for other languages? In particular, I have been trying to get the equivalent for Python, but I have not been able to avoid cmd printing one line before it restarts the script in the python interpreter (my closest so far: rem="""\[email protected] %~f0 %* & @exit /b %errorlevel%\n"""; del rem\n Cmd prints the first line: rem=""")Trahan
@Trahan - check this -> https://mcmap.net/q/409778/-how-to-insert-python-code-in-a-bat-fileGiron
Thanks! You have saved me from being nerd-swiped by this question for much longer than I can afford.Trahan
The association workaround (assoc, ftype) is nice for shell environments but this works in Windows API CreateProcess.Bullnose
You can see comment symbolsCitreous
U
1

Here is a simple way to force windows to support shebang however it has a caveat regarding the file naming. Copy the following text in to a batch file and follow general idea in REM comments.

@echo off

REM This batch file adds a cheesy shebang support for windows
REM Caveat is that you must use a specific extension for your script files and associate that extension in Windows with this batch program.
REM Suggested extension is .wss (Windows Shebang Script)
REM One method to still easily determine script type visually is to use double extensions.  e.g.  script.pl.wss

setlocal enableextensions disabledelayedexpansion
if [%1] == [] goto usage

for /f "usebackq delims=" %%a IN (%1) do (
  set shebang=%%a
  goto decode_shebang
)

:decode_shebang
set parser=%shebang:~2%
if NOT "#!%parser%" == "%shebang%" goto not_shebang

:execute_script
"%parser%" %*
set exit_stat=%errorlevel%
echo script return status: %exit_stat%
goto finale

:not_shebang
echo ERROR script first line %shebang% is not a valid shebang
echo       maybe %1 is not a shebanged script
goto finale

:usage
echo usage: %0 'script with #! shebang' [scripts args]+
echo        This batch file will inspect the shebang and extract the
echo        script parser/interpreter which it will call to run the script

:finale
pause
exit /B %exit_stat%
Untune answered 16/3, 2013 at 11:15 Comment(0)
L
0

No, there's no way to "force" the command prompt to do this.

Windows simply wasn't designed like Unix/Linux.

Is there a shell extension that does something similar?

Not that I've heard of, but that should be asked on Super User, not here.

Laski answered 25/7, 2011 at 14:57 Comment(1)
It is possible. See my answerPalatial
M
0

There's no way to execute random file, unless it is an actual executable binary file. Windows CreateProcess() function just not designed for it. The only files it can execute are those with MZ magic or with extensions from %PATHEXT% list.

However, CMD itself has a limited support for custom interpreters through EXTPROC clause. The limitation is that interpreter should also support and omit this clause in its execution.

Muckraker answered 21/12, 2017 at 12:21 Comment(0)
B
0

@npocmaka Thanks for the hint! After some trial and error I found the equivalent for a batch/php hybrid is as follows:

<?/** :
@echo off
C:\tools\php81\php.exe -d short_open_tag=On %~f0 %*
exit /b
*/ ?>
<?php
header('Location: example.com/');
print("<body><h1>Hello PHP!<h1></body>");
?> 
Bullnose answered 10/8, 2022 at 20:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.