Part of that is the lack of a history of automation - basic things to do with processes and I/O are kind of schizophrenic. All of the basics are clearly unix inspired (standard streams, processes, redirection - this is all unix-like), but many windows tools use different conventions to exchange data and control channels - powershell has a real object model.
In principle powershell's richer object model is a boon to automation - it's so much easier not to make mistakes if you don't need to massage your data through lots of slightly different text-based hacks, but the object model just isn't nearly pervasive enough. Sometimes you still need plain text/binary streams, and the transition isn't great. More fundamentally, the object model isn't well thought out - it's built on .NET, but that's clearly a single-process focused world view, and for a inter-process management tool, that poses problems. Even if sending objects between processes would work smoothly, there's the issue that objects don't compose or reflect as smoothly as text. It's hard to put your finger on, but for example, you can use things like regex's to do fairly fancy pattern matching on strings, and the equivalent for objects just isn't there in powershell. As a result, things work great if you're doing something that the underlying processes "want" you to do - but if you're trying to hack around some limitation, or try something novel, it's much more painful than in bash.
I think it's also worth mentioning some practical problems: Powershell is really slow and heavy. You can cheaply pipe and juggle data in a unix shell, but by doing that in powershell I've seen machines grind to a halt. A fresh powershell instance has a working set of 100MB on my machine; bash: 5MB. That's a problem. Startup time, similarly, is slow. This isn't a problem if you're working purely interactively - no human is going to notice an extra 10ms here or there, but in scripting, you can easily start so many processes that the difference becomes very noticable.
Powershell isn't terrible, but it just doesn't work as well as the unix shell, despite all the warts that has. Maybe some day everything will speak powershell, and it'll faster, smaller, and have a better story concerning pattern matching, but right now it's relatively ineffective compared to a plain unix shell, in my experience (which is windows centric).
As a JS guy, these days most of my scripts run via node/iojs and are as platform agnostic as possible. More and more I know it only needs to run in linux, or is guiding dockerization. Even then, bash scripts tend to be easier to reason about.
http://blog.idleworx.com/2010/01/windows-scripting-host-and-...
I've seen a few open-source projects actually use this. (IIRC, it was WiX)
The biggest issue with JScript in general is probably the lack of open options for certain classes of COM controls, that and COM collections are a beast (the enumeration wrapper you need in JScript is horrible). JScript was my preference just the same back with Classic ASP scripts. Could re-use my logic client and server-side, which usually worked out pretty well... though almost everybody used VBScript, which usually meant in a project both engines were loaded on the server. The other issue was runtime initialization for every request meant you were somewhat limited, though for a couple hundred users on a system at once around 1999-2002, it wasn't bad.
bash gets a bad rap, because there's a ton of horrible shell scripts floating around. For some reason, when people write in bash, they decide that since it's not a "real" programming language, they don't need to take it seriously. They will UPPERCASE all variables (so ugly, and stems from lack of understanding - you're supposed to uppercase environment variables only), fail to make use of functions, fail to make use of variable scoping, invariably choose the worst available comparison tools ("["), fail to make use of appropriate utilities (which is particularly egregious, considering the fact that the utilities (coreutils, moreutils, etc.) are the API of shell programming).
This is rather unfortunate. Well written bash is efficient, and, dare I say it, can be elegant. Of course, there are nicer shells around - zsh comes to mind - but bash is fine.
For the sake of political correctness, I shouldn't say this, but I will say it regardless - Windows Powershell does not come close to the feature set or expressiveness that bash+the Linux userland can have in the hands of someone who knows what they're doing.
See Powershell's Start-Job[0] Get-Job[1] Remove-Job[2].
> Windows Powershell does not come close to the feature set or expressiveness that bash+the Linux userland can have in the hands of someone who knows what they're doing.
Well nobody can argue that Powershell doesn't have just under fifty years of back-catalogue. That's obviously a massive advantage and head start, as is the expertise that comes along with it.
As to the "expressiveness," I'd need to know more specifically what you're referring to to address that point.
[0] https://technet.microsoft.com/en-us/library/hh849698.aspx
[1] https://technet.microsoft.com/en-us/library/hh849693.aspx
[2] https://technet.microsoft.com/en-us/library/hh849742.aspx
Some people avoid a lot of the things in the coreutils/moreutils toolbox because they need their shell scripts to be portable between *nix types, and not everything in there is POSIX compliant, even if you set POSIXLY_CORRECT, or even when it is, the syntax is different. I could go through the trouble of having the script check what type of system it's running on and then select the proper flags and syntax, or I could just write something that will work everywhere that might not take advantage of some "feature" found in coreutils.
I remember when this was the most common defense of VB :D
Powershell reeks of development with C# on Windows. You have specific function calls that can do very niche things such as convert an application to a virtual machine in IIS. The problem comes up when you are trying to do something novel or just out of the scope of what Microsoft thought up. Bash allows for those things by having separate and reusable components that do their one job well.
Get-Object and Set-Object don't work universally as advertised so you can't just write boilerplate and expect things to work. Instead, you have to google "how do I set up a virtual application?" or "how do I change bindings to an existing virtual application?" You'll get the job done, but you won't feel like you learned anything. I'm glad you wrote this up. It's been something that's been bothering me, but I was having difficulty verbalizing it.