Long ago I thought about writing something that compiles to batch files, if only to make complex logic a bit easier to write or make the process of thinking about every little syntactic idiosyncrasy less tedious. Since then I found PowerShell though, and the need of writing complex and sophisticated batch files isn't so much there anymore¹.
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.
The main issue with powershell is portability - no guarantee that someone's Windows box will have it installed or not.
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.
You have that guarantee starting with Windows 7. Version is one thing; some nice things are available only in v3+, but v2 is very usable already. Execution policy is another matter, but you can always supply a batch file with the PowerShell script containing
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.
| You have that guarantee starting with Windows 7. Version is one thing; some nice things are available only in v3+, but v2 is very usable already.
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:
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.
This is not an example of evolving syntax. It's just a bunch of parameter sets added to Where-Object. New syntax is the -in operator for example (reverse of -contains).
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.
Point being that it's easy to write a script that works fine on v3/4 but fails when run on v2, without doing something incredibly obvious like using cmdlets or modules that didn't ship with v2. Here is a by-no-means-comprehensive list of potential gotchas:
• 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.
• BadNumericConstant
I thought powershell had to be explicitly installed/enabled even in win7.
I'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...
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.
Powershell is actually a really nice shell/scripting language. I often miss its power, simplicity and not to mention the immense amount of flexibility having all of .net accessible when using a 'nix box.
That sounds like a symptom of simply being more familiar with the Windows environment. People who have grown up in China probably find chopsticks simpler and more powerful than forks -- I'm hypothesizing -- but not because forks don't work.
I wouldn't say so. I would kill for a halfway decent Ruby shell. On Windows I'd be going on about the power of .net and on nix I'd be promoting how awesome having the power of gems in my shell is. Powershell really is quite good and blows sh/bash/zsh out of the water. The "everything is an object" model instead of passing around strings really changes how you work.
I know far more about scripting linux/unix than Powershell, so I can't really speak directly to Powershell's strengths and weaknesses. But there's reason to be skeptical that Powershell has actually blown bash out of the water, I think. If it made that much difference, linux/unix would have adopted Powershell's object paradigm for itself.
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.
Powershell is available on every Server install since 2008 R2. At this point it can be considered standard on every non-ancient Windows box, similar to assuming bash vs sh for example.
This is great for me. As part of my day job I am often stuck writing batch scripts (yes, in 2014) for clients that refuse to run powershell. Writing a simple batch script is usually not a problem, but it can be very encumbering as the complexity increases.
I want to agree, but my major gripe using the different incantantions of Powershell (and I have tried, I am Winboxen admin often in my job and tried it before any other co-worker on Vista, obviously the story has improved since) and the startup time and performance was abysmal.
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.
The speed difference between PS and cmd.exe is not nearly large enough to justify the incredible hoops you have to jump through to get anything reasonable done in batch. Yes it takes slightly longer to start up, but it has things like native arrays, hashmaps, foreach loops, etc built in to the language! Versus a spaghetti mess of gotos in batch.
As I said in the other threads, the language is great, the performance has been abysmal in relation to batch (at least for me, having started with Powershell in its first release in Vista).
With PowerShell level of slowness it starts to matter. Even very basic commands seem to sometimes take many seconds to run. In the middle of intense workflow it becomes a problem.
What could a shell possibly do so that a basic command would take many seconds?
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.
Care to give examples? I know that the language isn't fast, but afaik nearly all shells are interpreted. There have been performance problems with break/continue in earlier versions as they were implemented using exceptions internally. But that doesn't really qualify as "basic commands", I guess. Cmdlets should be not much slower than running the equivalent C# code yourself.
Hmm, I can't seem to reproduce many such issues with this machine, except Get-Help the first time I tried it. I think it could be that the cmdlets are only slow on the first run (enough to leave me with a bad experience), or the SSD on my PC masks the problem. It's good to know that it's not always super slow.
If it's slow on the first run, then it might be loading a large interpreter from disk. If so, MS might have let the interpreter get a bit ungainly -- you might argue.
I use Powershell for many administrative tasks at work, and it can be annoying if querying data from a single machine takes 5+ minutes. Which it does sometimes.
For simple use cases I still use batch files as the performance is much greater. Powershell feels too heavy when I just want to run a build with some parameters and a couple of other commands.
I think it's really interesting the way programmers will use phrases like, "it feels heavy", as a way to describe using programs that contain unused features. I'm guilty of the same. Powershell "feels heavy" because it is a lot more sophisticated than batch, you can do all sorts of cool things with WMI or use data structures, but in the end, what does programming in batch actually gain you? If performance is such a problem that you notice a performance penalty when switching between shells, something is seriously wrong.
But I'm guessing you don't really notice the performance difference, you just feel the weight of unused features.
The opposite effect is, IMO, how things like node.js gain in popularity - the environment "feels fast" and "feels simple" [for the simple use cases that are always at the start of things].
Totally agree. Powershell is what you need to use on windows. It's been available on the default server install since 2008 R2. No need for batch scripts anymore.
This sounds like you're saying that it suits your needs, therefore we should take that as meaning it fits our needs. Unfortunately, things are not that simple.
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.
There's a config switch to allow execution of scripts. I agree it's a complete pain (literally falling at the first hurdle), but it is a one-time thing change.
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
Thanks for this candid impression. I had some slight interest in learning PowerShell, but it looked like a little bit too high of a learning curve, given that I had other scripting languages I could use (including bash in Cygwin). Piped objects struck me as interesting when I read about it in a magazine, too, but somehow they aren't needed to perform all kinds of scripting in *nix, so I wonder if they might be more complex than the problem called for. I get the impression that PowerShell may suffer from having come from Microsoft -- a company with bottomless pockets to spend on developing software and probably little need to stop smallish system utilities from becoming ornate.
On the contrary, one of the first things I do on a Windows box is open up a powershell window. Especially on Win 8+, it's a lot easier to do "logoff" or "Stop-Computer -Force" or "Restart-Computer" than to try to navigate the mess of Metro to find the GUI menu options. Moving files around on the PS command line is much more efficient than using Explorer, just like bash/Terminal on the Ubuntu desktop. It's just a matter of getting used to it (and learning the different syntax from Unix shells).
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.
I beg to differ, and not only because I code-golf in PowerShell. Aliases and the ability to shorten arguments while they're unambiguous both are features that have no use for scripts, but are very handy for an interactive shell. I never type things like
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.
This implementation is not perfect, although it's interesting that it supports Windows. I personally don't care about that, but it brings the idea to create some sugary wrapper around Bash that allows you to use Bash v4 features such as associative arrays in Bash v3, and wrappers that allow functions to return arrays and other typical headaches.
My initial thought after seeing this is Windows support is interesting, but the real value is in making bash friendlier. Something that brings syntactic sugar to bash is welcome in my mind, as I always find myself putzing with Google to find solutions to even slightly non-trivial scripts.
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.
>> 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.
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.
1. From UNIX point-of-view, not all has the luxury of bash, so seems to be quite limited to a certain modern platform? I found out ksh are more prevalent
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
Using Fedora 20, `which ksh` returns nothing. I would think people wanting to adopt a language like this are more likely to be using Linux 2.6 than AT&T UNIX, but I would suspect you're wrong about which one is now more prevalent now anyway. I can't remember the last time I used a *nix box that didn't have bash (or a VERY similar shell) installed by default, and this is certainly a huge step up over having to write both batch and bash independently anyway.
What systems do you work on where bash isn't around, but ksh is?
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'm not so sure about the utility of this in my case. I usually end up using python for scripts, with perhaps a one line batch file that runs it with some default arguments for convenience.
Yup, that's all we end up doing, but it would be nice to have something that combines both programming bliss with end product being just one Bash script that runs on every Linux distro.
I have to confess, that I'm also one of those guys. I usually anyway installing Python anyway. So using it all scripting is trivial. Even if Python is "heavy and slow", people seem to forget that Powershell is lot heavier and slower.
There's no mention of error handling, which is what really makes Windows batch files completely hopeless for anything involving more than one or two commands. Being able to write code with exceptions and having it compiled to the corresponding mess of ERRORLEVEL and GOTO would be sweet!
(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.)
So are we really supposed to install OCaml and compile it or do we use it as a hosted service? I can see that you just post a batsh script and specify your output, but I don't know if that's intended for public consumption. Otherwise this just looks like a POC.
I think you missed the second option in the README, “Install from OPAM” (https://github.com/BYVoid/Batsh/tree/master#install-from-opa...). To summarize, you can install the OPAM system with your package manager with a command such as `brew install opam`, then install batsh with `opam install batsh`. That should give you a `batsh` command that you can use to compile your scripts.
That files() function will not work properly.
I have an old abandoned project, that has a proper directory listing function for batch, you can take that.
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.
I had to do this once to avoid having to duplicate a bunch of build and install logic (that couldn't assume some other scripting language was installed), but because of how limited batch is (powershell was not available at the time), I opted to write a simpler DSL that output one or the other. I could see this project developing in that niche by maybe providing more substantial built-in functions for common build/install script functionality.
I want this to be great; it would solve no end of problems at my workplace.
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.
They are both hideous languages with myriad diverging features. Translating them into each other would either require extra runtime dependencies or obscene amounts of hideous code in either language.
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.
Don't get me wrong, I wasn't attacking OCalm, nothing against it, I'm curious about Functional Programming, I've yet to try them for serious projects. It's just not in my toolset currently. Also I'm trying to maintain a rule whereby I don't install software I don't use frequently. OCaml might be nice, but I'm rather unlikely to use it as much as I use the other programming languages in my system. I appreciate that this solution is offered as a web service.
One peculiarity of batch files, and how cmd.exe executes them is that they are being read over and over (or maybe they are simply mapped file).
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.
Having just written a Nagios plugin with json parsing in bash (main design goals were no dependencies or support code/modules needed) and then 'ported' it to batch, I look forward to trying this.
Love the idea of writing bash in a higher, easier to read format, similar to CoffeeScript. Unfortunately Batsh is written in OCaml (the author addresses why he uses it though).
Only half-way; it doesn't stream the data, it waits for the first command to finish, saves the entire output, then starts the second command with output as input.
I can't think of a case where seamlessly having two different targets like this has worked - particularly if there's pressure to really support all of the features of both.
Unity 3d. Haxe. [1] GWT. [2] There are tons of cross-platform toolkits that do this for games; having something that does it for SHELL SCRIPTING seems trivial by comparison.
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.
These days, if I'm writing something in bash (or batch) it's often because there is nothing better available - like kicking off an installer, or some other wrapper / bootstrap script.
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 don't like the concept so much. They are their own languages, and I'd rather write very low level ansible primitives and build upon them than rely on a somewhat opaque translation process. Also, all automation I do going forward is PowerShell, not batch.
I could see a lot of places using it, though, so bravo for sharing.
I posted it here to start a discussion not as an endorsement as we have all kinds of sugary compilers - for JavaScript and other languages, but none of Bash. Cross-platform support would be nice and as others have pointed out, PowerShell really took over Batch especially when Microsoft took care of the slow loading issue. I personally would rather have an extension of Bash rather than a brand new language, but that's me. In fact, I've been thinking of a simple preprocessor that even combines a bunch of scripts into a single one for easier distribution.
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
into 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.