I'm not an expert, but I use UNIX/Linux at work and only Windows at home (I have a dormant Arch Linux install that I haven't touched in a couple of years), and hopefully you think I'm qualified to respond.

I feel Bash is a 'glue language' in every sense of the word, and is optimised for interactive command-line usage because of its terseness. Being remotely productive on Bash presupposes the presence of an entire UNIX subsystem and coreutils (which is why Git Bash for Windows drags along an entire `/usr/bin` directory with all the coreutils in it). You can't really do much in it without the coreutils.

I find that Bash parseability and ease-of-understanding rapidly deteriorates in scripts of increasing complexity. After about a hundred lines of code I reach for other languages. I personally dislike its unintuitive syntax, global scope, and weak, dynamic typing. The terseness that lends itself to powerful interactive command-line usage means script readability plummets. Of course, that might just mean I'm inexperienced with respect to Bash and need more practice, but I find this a fairly common opinion amongst colleagues and friends. In my opinion, Bash scripts are write-only. It is a wonder that something like neofetch[1]—which is an eleven thousand-line monstrosity—lasted this long (if I recall correctly the author stopped maintaining it because—amongst other reasons—it had just become too complicated).

I find that people understand PowerShell better when they realise it is closer to Python than any interactive UNIX shell. By default, PowerShell is more verbose than Bash; for instance, the PowerShell equivalent of the two-character all-lowercase `ls` is the thirteen-character mixed-case `Get-ChildItem`. Arguments are by default also long and verbose, with things like `-FollowSymlink`. PowerShell is generally meant to be used in executable scripts, just like how most Python isn't executed in the interactive REPL, but by running scripts. Consequently, I find this verbosity lends itself to improved readability in scripts, at the expense of some interactive productivity. That being said, common PowerShell commands have UNIX-like aliases[2] (at one point the cause of much gnashing of teeth here and at /r/programming because PowerShell aliased `curl` to `Invoke-WebRequest`[3]) to improve interactive productivity. PowerShell also supports truncating parameter names; for instance, `Get-ChildItem -Recurse -Force` can be abbreviated to `gci -r -fo`, which looks remarkably like a UNIX command now. Even so, the PowerShell ISE and the PowerShell VS Code extension both suggest that programmers use the full unabbreviated commands and arguments in `.ps1` scripts[4].

PowerShell is also dynamically typed, though semi-static typing can be opted in to[5]. That said there is some controversy about arrays decaying to scalars when they have size 1 [6]. It is easy to set up both function and script parameters with as much power and expressiveness as `argparse` for Python, but natively without involving any additional modules[7].

The real power (pun not entirely unintended) of PowerShell comes when you realise it is just another front-end to the incredibly massive .NET ecosystem. Where Bash requires a full UNIX subsystem and a collection of hundreds of additional binaries to be productive, PowerShell employs pre-compiled cmdlets[8] written in .NET (usually C#) to augment the basic language. Most 'commands' in PowerShell are cmdlets, including `Get-ChildItem`. You can write your own 'back-end' in C#, F#, C++/CLI, VB, or any other .NET language, compile it, and expose a PowerShell interface for end-users. Pretty much like how people write fast but complex code in C/C++, compile it, and expose a Python interface (Numpy, Pandas, PyTorch, etc come to mind). You can additionally directly call .NET methods in PowerShell[9].

This also means that everything in PowerShell is an object. The output of `Get-ChildItem` is a list, not a string. Likewise for `Get-Process` (UNIX equivalent: `top`). These lists may be formatted[10], filtered, parsed, modified, dumped to JSON, and otherwise manipulated like any other list data type in most other languages.

PowerShell also lends itself to the side-effect-free/functional/monadic map-reduce paradigm very well, with pipelines[11].

In my opinion, it is not merely 'better than CMD'; it blows CMD out of the water. A little less so for Bash, because Bash is augmented by the UNIX core-utils. As should now be evident, in my view the real competition to PowerShell is Python.

[1]: https://github.com/dylanaraps/neofetch/blob/master/neofetch

[2]: https://learn.microsoft.com/en-us/powershell/scripting/learn...

[3]: https://news.ycombinator.com/item?id=12319670

[4]: https://learn.microsoft.com/en-gb/powershell/utility-modules...

[5]: https://stackoverflow.com/a/115815/1654223

[5]: https://superuser.com/a/414666/1132163

[7]: https://learn.microsoft.com/en-gb/powershell/module/microsof...

[8]: https://learn.microsoft.com/en-gb/powershell/scripting/power...

[9]: https://devblogs.microsoft.com/scripting/learn-how-to-use-ne...

[10]: https://learn.microsoft.com/en-us/powershell/module/microsof...

[11]: https://learn.microsoft.com/en-gb/powershell/module/microsof...