Batsh – A language that compiles to Bash and Windows Batch
batsh.org
batsh.org
Nice to see this compiler adopting some idioms that make it easier for working with larger codebases, e.g. passing a return value variable name into subroutines. The author apparently lacks a bit of understanding on how to write robust batch files, though. Turning
x = "a|b";
into set x=a|b
is surely going to cause trouble. Quoting the argument to set is also often much easier than correctly escaping every meta-character. And iterating over files by throwing for /f at dir's output will cause trouble with filenames that use characters outside the current legacy codepage (not to mention that /w is the wrong switch and /b must be used, otherwise you get funny "files" back like Volume, in, drive, C, ...). Testing their language and output for correct functioning apparently wasn't high on the list, or at least, as usual, only for bash.(Bugs reported, but the choice of implementation language makes pull requests a bit hard for me. It also seems that the language is unusable for anything but simple stuff. readdir() returns a string with space-separated file names, but there is no way of iterating over them again (and it's not easy in batch files). Things like iterating over arrays or better support for printing text that does not cause trouble or side-effects have been known for over half a year without a change. I guess the project, while nice, is currently a zombie.)
____
¹ Last thing I really wrote was a deployment script for a website that had to run on Server 2k3 instances where I wasn't allowed to install anything. And I still have a half-written bignum library in numerous batch files somewhere. Only addition worked properly, though.
I recently wrote a batch script just to make sure it'd run on any Windows system rather than risk powershell. If it was always going to run in a controlled environment, I'd have written it in cygwin bash anyway.
powershell -ExecutionPolicy Bypass -NoProfile -File %~dp0.ps1 %*
That's what I usually do, which is also helpful for colleagues who have no idea how to run a PowerShell script because just double-clicking it doesn't work.Often I start with a batch file, just to notice after a dozen lines that this sort of thing is much easier to write and maintain in another language. And in the last two years I shifted more to PowerShell than batch in many cases. Some of that is surely due to atrocities like Windows XP dying out and Vista never being common. For scripts that developers execute on their machines PowerShell should be a fairly safe bet in a Windows environment by now. Deployment or build scripts should probably be MSBuild or something similar.
I love me some Powershell. Wrote my first non-trivial PS script in early 2010 that was a major component to building something I would now call "Continuous deployment of Windows OS images."
But I still have way more lines of BAT in production than PS1 because the versioning is a nightmare. v2 was the first really usable release and it ran everywhere I cared about except for Windows PE. v3 got some nice enhancements and support for Windows PE, but dropped support for anything older than Windows 2008. v4 added some more but took away Windows 2008 R1.
If it were just that newer versions of Powershell offered new modules and cmdlets it wouldn't be such a big deal, but the syntax itself has been evolving. This is valid in PS v3+ but not in PS v1/2:
Get-Alias | ? Definition -eq Where-Object
For PS v1/2 you'd have to write it as: Get-Alias | ? { $_.Definition -eq "Where-Object" }
Many landmines are out there waiting if you need to write a script that can handle multiple Powershell versions.There are plenty of sucky things about BAT files... But they are truly lowest-common-denominator on any Windows system, there aren't any syntactical landmines waiting to get you with different Windows versions since 2003, and for anything you want to do on Windows that you can do with Powershell you will certainly be able to find a command-line tool that lets you do the same thing with Batch.
However, I find myself using the new parameter sets for Where-Object very infrequently. Since they can only model
Property -Operator Value
their use is limited to certain operations, which I find myself to need not that often. And if the conditions get more complex I need to write a scriptblock anyway, having to refactor your former form into the latter. • Operation Statements vs Script Blocks
• Several new operators
• Changes to $PSScriptRoot and $MyInvocation
• Stop parsing symbol --%
• Ordered dictionaries
• New redirection operators
• Count and Length properties added to "arrays" of zero or one
• Retrieving a property from a collection that only exists in the individual items returns the value from all items.
• BadNumericConstantI'm not going to walk a user through that when I can do what I want in batch (with more pain, but still less than ending up providing support...).
My normal area is Linux though, and both powershell and batch make me appreciate bash so much more. Even those little things like being able to format arbitrary dates as you want...
> Even those little things like being able to format arbitrary dates as you want...
You mean like
$someDate.ToString('yyyy-MM-dd')
'Today: {0:yyyy-MM-dd}' -f (Get-Date)
Get-Date -Format yyyy-MM-dd
date -f yyyy-MM-dd
Right, that's excruciatingly hard in PowerShell (hey, you even get Unix date format strings with Get-Date -UFormat). (But I guess we just come from different worlds here, as every time I have to read or write bash scripts it makes me appreciate PowerShell so much more.) Granted, the batch variant is ... not as pretty: for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x
echo Today: %MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%
And I found the PowerShell script alongside with the batch file a pretty workable solution. Nicer language and still something for clueless users to double-click.I'm not sold on Ruby gems. I haven't learned Ruby yet. Shell scripting to me means bash (or /bin/sh) + whatever utilities come standard on a unix system: sed, awk, etc.
The goals may be slightly different, reflecting the different cultures using the shells. What I think is cool about bash scripting is that I use bash constantly, anyway, which makes it easy to test small script fragments before including them in a full-on script, and even though, e.g., some things are nasty to do syntactically in bash, I get lots of practice.
Yes, it's on all Windows Server installs, but those are not all windows boxen by a long way.
Thank you for sharing.
In terms of performance for very basic scripts (silent software installs, 5-10 lines, registry patching, etc.), I see the performance chart as:
Batch > VBScript > Powershell
in terms of speed. I wish I had tried Jscript, because the ironic Javascript is taking over the world could have meant retro hipster superiority (and scary you could integrate JScript and VBScript into the same script by embedding them in XML type directives and using the WSF system). Now that was scarier than any of this.
As an aside, outside of speed, how do you sign scripts for clients? I love that Powershell encouraged it, but every person I have met has not bought into Powershell, and most certainly invokes "disable the cert check" completely command for all executed Powershell scripts.
Currently, "many seconds" is enough time to run an interpreter on the command, connect to a remote machine in Iceland, spin up a new virtual server there, send the command there to be executed, review the execution results for possible exceptions, run a malware scan, fetch the response back, execute the command again on your computer, translate the command and results to Klingon, send them to NSA for archiving, play a quick game of chess with another instance of the shell, and play a congratulatory tune.
Seriously, computers nowadays are fast enough to run a partial compile of your code at every single keystroke while you're writing it. It takes special effort to make a scripting language unusably slow - even an unoptimized interpreter that itself runs on a different interpreter should do just fine.
But I'm guessing you don't really notice the performance difference, you just feel the weight of unused features.
I needed to do something and looked at using powershell, but in the end I couldn't just distribute it and have it work for whomever would be using my project. It needed to be signed or something. On the contrary, the bat script I wrote just worked and would just work for anyone who used the project.
Powershell is not a magical solution that suits everyone's needs. This kind of blanket statement helps no-one.
I had mixed opinions of powershell when I tried my hand at it. The naming convention and documentation system were well designed, piping objects is an interesting concept, and IDE support was great for a terminal (step through debugger, intelligent auto complete). Despite this, there were numerous quirks and ugly spots that diminished the experience. I felt it was a missed opportunity. This was powershell 3, I can't speak for later versions
PS> Set-ExecutionPolicy Unrestricted
It's the first line of just about every publicly-distributed script (including Chocolately, etc).PS cmdlets in generally are quite consistent: there is a [Verb]-[Noun] naming convention (eg, "Stop-Computer" above) and full tab completion, so if you forget the exact name of a cmdlet you can do Get-[tab] and cycle through every Get-* cmdlet that exists. Even command line switches tab complete, just type a hyphen and then you can tab-cycle through every command line switch that particular cmdlet supports. There's also Remote Powershell, which is like SSH but also built-in. I can sit in a Powershell window and connect to a Windows server anywhere just like SSH on Linux, or even compose a script block, assign it to a variable, then send it over the wire to be executed remotely (or to a group of machines in a foreach loop). It's pretty slick, and all this is built into the shell--no third-party tools required.
I'm not a big fan of MS, but I'm willing to give them kudos on the rare occasion that they build something nice. Powershell has it's quirks like anything, but it's a damn nice piece of engineering and a godsend to anyone who has to administer Windows boxes. Why anyone would continue with the anachronism of (essentially DOS) cmd.exe is beyond me.
Get-ChildItem -Path ~ -Recurse
if I can help it, instead it almost always is something like ls ~ -r
I guess -Recurse only ever appears there if I hit [⇄] for parameter completion.Sadly there are far too many people who only know bash and see straightforward conversions of VBScript into PowerShell and think the language sucks or is too verbose.
Perhaps I should just master bash scripting once and for all (I know it's not that complex), but I generally find it unpleasant to do anything that requires control flow or traditional "programming language logic" in bash.
A simple way to bootstrap the compiler with the script itself would be especially nice. Basically, an embedded batsh compiler. Might be an interesting avenue for an enterprising person to look into.
Most of the time I find myself struggling with Bash, it's because a simple script has kept expanding in scope and I'm well into the sunk-cost fallacy in trying to fix "just that one last thing".
But unless you have a really specific environment, I'm pretty sure most modern servers probably have Python or Ruby or some other stack that can be a shell script available. If you're in Bash, it's because you were trying to do something quickly.
This could be very easy. If this can't be rigged with simple shell scripting (in a reasonable way), then it could with straightforward changes to the compiler (such as outputting to standard output). If you don't mind doing somewhat silly things like writing out scripts as temp files, this could certainly be done now.
Key feature has to be output that is no less readable than the average bash script. Which it seems to be.
So does smashing your head into the keyboard while holding the shift key.
I use bash but it's not a pretty language.
2. I actually use UnxUtils in windows so I can has POSIX command option (and scripting). Performance-wise, never tested as not needed, all short command / simple script
If you're referring to Linux as "certain modern platform", I was using bash on Solaris 1.x 20+ years ago. (Granted, back then I had to compile it myself which may not be an option for many.)
(I've switched to just writing everything in JavaScript for WSH. It's ECMAScript 3 and the API has some issues, but it's still a million times better than trying to write any logic in batch.)
You can also put a thin shim to launch node for the script in case it's in a wsh environment.
WSH is Windows Script Host: https://en.wikipedia.org/wiki/Windows_Script_Host
http://sourceforge.net/projects/scriptconvert/
Much of the stuff there is half assed but there is some goodies. Like substring searching and dumping of stdout without using temporary files, which is insanely weird in batch definitely take a look.
Unfortunately, "You have to install OCaml (version 4.00.1 or higher) development environment before compiling Batsh" (not to mention "1. Install OPAM. See instructions.") basically makes it a non-starter for my purposes.
Why can't this take a batch file and translate it to Bash? Or vice-versa? Genuine question - I do not have a sufficient understanding of the fundamentals to guess.
By coming up with a third language the author could conveniently pick a subset of features that could easily be implemented in both languages without much goat slaughtering.
I've found this by trial-and-error - while I was editing a batch file that was executing, it would suddenly error out with meaningless info, sometimes it'll print out the things I've just added to it.
Try this:
$ echo 'echo hello; sleep 2' >/tmp/hm.sh; bash /tmp/hm.sh & (sleep 1; echo 'ls /bin' >>/tmp/hm.sh); sleep 3..and why wasn't this posted 2 weeks ago!
How do you use pipes in batsh?
Just googled it. Doesn't seem to be supported yet: https://github.com/BYVoid/Batsh/issues/17
Sure it is: http://www.microsoft.com/resources/documentation/windows/xp/...
Yes it does happen that some features get neglected, but we're talking shell scripting here. They could hit the 80% use case and it would be totally useful.
[1] http://haxe.org/
For those kinds of simple tasks, the overhead of fully understanding the nuances of bash _and_ bash is way more trouble than the inconvenience of having fewer features available. This is not for bat/sh lovers, it's for those who have to use bat/sh even if they'd rather not.
Having said that, I wouldn't use batsh myself until it does something sane with errors (at least the equivalent of `set -e` in bash).
I could see a lot of places using it, though, so bravo for sharing.
Also, why hasn't this been around before?
Batsh -> Bash or Batch