Today I wanted to write a script that I could execute from both *nix (using Bash or a similar shell) and on Windows (from a command prompt, i.e. a batch file). I found Max Norin’s solution which works, but has a few limitations, e.g. when run it outputs either the word “off” when run in *nix or the word “goto” when run on Windows. There’s got to be a sneaky solution, right?
Here’s my improved version:
1 2 3 4 5 6 7 8 9 10 11 12 |
@goto(){ # Linux code here uname -o } @goto $@ exit :(){ @echo off rem Windows script here echo %OS% |
Mine exploits the fact that batch files can prefix commands with @
to suppress outputting them as they execute. So @goto
can be a valid function name in
bash
/zsh
etc. but is interpreted as a literal goto
command in a Windows Command Prompt. This allows me to move the echo off
command –
which only has meaning to Windows – into the Windows section of the script and suppress it with @
.
The file above can be saved as e.g. myfile.cmd
and will execute in a Windows Command Prompt (or in MS-DOS) or your favourite *nix OS. Works in MacOS/BSD too, although
obviously any more-sophisticated script is going to have to start working around the differences between GNU and non-GNU versions of core utilities, which is always a bit of a pain!
Won’t work in sh
because you can’t define functions like that.
But the short of it is you can run this on a stock *nix OS and get:
$ ./myfile.cmd GNU/Linux
And you can run it on Windows and get:
> .\myfile.cmd Windows_NT
You can’t put a shebang at the top because Windows hates it, but there might be a solution using PowerShell scripts (which use
hashes for comments: that’s worth thinking about!). In any case: if the interpreter strictly matters you’ll probably want to shell to it on line 3 with e.g. bash -c
.
Why would you want such a thing? I’m not sure. But there is is, if you do.