Kevin Gallo just announced Bash support on Windows.

If you have never had to interact with the Windows Batch language, this might not seem like such a big deal. Surely Batch could not be substantially worse than Bash, right?

Bash: a language that was neither designed, nor evolved. An adequate solution to a problem that has since become orders of magnitude harder. As arcane as it is useful, as dangerous as it is ubiquitous, Bash: the language that asks how much we are willing to give up for convenience’s sake?

Sure, Bash could be worse. But substantially worse? Bash had one value proposition: it was just good enough. It is difficult to imagine that it would have flourished as it has, if that had that not been true.

But the truth is what it is. Batch is substantially worse. And how much worse sort of beggars belief. Look:

The time a batch script takes to execute is at least O(n*(n-1)/2) (aka O(n^2)) in the LENGTH OF THE FILE, INCLUDING COMMENTS. The reason is that the batch engine reads the entire file, then executes a line, then reads the file again, then executes another line, and so on.

It is therefore customary to use a GOTO to skip over sizable comment blocks, so that you don’t have to “execute” them.

The lines inside “lexical” blocks like those of the for loop are not interpreted separately. They are CONCATENATED TOGETHER AND INTERPRETED ALL AT ONCE, meaning that if do something as innocuous as adding a :: comment inside a for loop or an if block, the terminating ) will go missing and batch will not know what to do. It will think that you forgot to add a ) to close the for loop.

loop are not interpreted separately. They are CONCATENATED TOGETHER AND INTERPRETED ALL AT ONCE, meaning that if do something as innocuous as adding a comment inside a loop or an block, the terminating will go missing and batch will not know what to do. It will think that you forgot to add a to close the loop. Never comment out code. If you, do bad things will eventually happen. For example, on some Windows systems, the REM -style comment, REM Ensure > true , will actually pipe the “output” of the comment to a file called true . Since comments have no output, the effect is to generate an empty file called true .

-style comment, , will actually pipe the “output” of the comment to a file called . Since comments have no output, the effect is to generate an empty file called . Variable expansion occurs at PARSE TIME, not evaluation time. This is particularly bad in the case of blocks like for and if , because all the lines in the block are concatenated together and parsed at once. So, normally if you call something like findstr inside a for block, you would expect %errorlevel% to be set to indicate whether there was an error. But, it’s not. The variable %errorlevel% is never updated, because it was assigned whatever value it had when Batch PARSED THE for BLOCK. The statement if %errorlevel% neq 0 is therefore completely meaningless inside a for block.

and , because all the lines in the block are concatenated together and parsed at once. So, normally if you call something like inside a block, you would expect to be set to indicate whether there was an error. But, it’s not. The variable is never updated, because it was assigned whatever value it had when Batch PARSED THE BLOCK. The statement is therefore completely meaningless inside a block. If you add 2 :: comments in a for block, you will get errors that claim The system cannot find the drive specified and there is a possibility that your script will exit with error code 123. This happens because (in spite of popular guidance that you should use :: as a comment) it turns out that the :: comment syntax is actually not a comment at all, but a LABEL, and in label syntax, :: must be at the beginning of the line with no leading whitespace, and two consecutive labels causes batch to freak out, because batch concatenated them together into the same line.

And the list goes on and on.

When I was in college a few years ago, I thought that PowerShell was a fun take on what a modern shell could look like. It is not. PowerShell is the cure for polio, and Jeffrey Snover is the Jonas Salk of the Windows ecosystem.

Batch is like an alien device that has appeared on the earth, and at first you think it’s a gift, but then you realize it is a machine of destruction, here to raze your society to the ground, and the only viable solution is to find a way to rid yourself of it completely.

Like the Necronomicon or some other Satanic book, Batch does not seem so bad at first, but when the correct medium (in this case, the computer) reads the words, you find that a portal to hell has opened and suddenly the trees are coming alive and you’re being sucked into your computer screen you’re thinking about how 10 minutes ago your biggest problem was whether you were going to get to the store in time tonight to grab that macaroni you like, and now, as you are floating through the demon portal, you’re just wondering why this thing didn’t come with a warning on this side or something like that.

Bash is like the neighbor who seems nice and sweet, but maybe they don’t have a life you’d want to have personally. They have some pretty serious character flaws and obviously make mistakes, but in the end they are a nice person who tries hard to make sure the people that depend on them are doing ok.

Batch is the guy who looks like that neighbor, but then turns out to be a serial killer.

So, here we are. This is the reality of the Windows world. Yesterday, your choice was Batch or PowerShell. Today your choice is Batch, PowerShell, or Bash. (Well, it’s not really as simple as that, but you get my point.)

And as you make your choice, it’s worth visiting the graves of the fallen.

Please enable JavaScript to view the comments powered by Disqus.

Disqus