The Scripting Guy Blog is Microsoft's official blog on PowerShell scripting, covering registry access, .NET use, and automation.
HN commenters cite it for PowerShell details, such as JSON handling, cmdlet naming, and zone identifier streams.
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…
i've never used nushell, but i've always felt that people have been sleeping on PowerShell.
yes, it was _originally_ only for Windows, but PowerShell 6+ uses .NET Core, which is OS independent. this means that a few helper functions like GeneratePassword[0] are gone, but it's _mostly_ at parity with .NET.
the Verb-Noun structure can be confusing at first, but once you know the approved verbs[1], you can usually guess your way through command discovery, which is not something i can say for most POSIX tools (useradd and adduser do different things!!)
it's also object oriented by design, with default aliases like ?[2] and %[3], querying structured data is a breeze.
- want to check a CSV? Import-CSV[4].
- want to call a REST/SOAP endpoint? Invoke-RestMethod[5] has you covered.
- DNS queries? Resolve-DnsName[6]
as it's built on top of .NET, you get the whole CLR[7] at your fingertips! you can make a TCP client[8] in PowerShell, or even just write C# directly in your terminal[9] and execute it the same way.
such a flexible and useful language, even if it is a little slow and owned by micro$oft. but it _is_ open source[10]!
---
[0]: https://learn.microsoft.com/dotnet/api/system.web.security.membership.generatepassword
[1]: https://learn.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands
[2]: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/where-object
[3]:…
Honestly I do not really understand this idea because, AFAIK, JSON was designed for Javascript in a web browser. By and large, Javascript-enabled web browser expect access to generous amounts of memory. This is not the case for the common UNIX userland programs. These programs do not expect large amounts of memory and many are written with the intent that they may be used to process text line-by-line. This JSON idea reminds me of Windows "PowerShell". Microsoft actually has to limit how much memory can be used by the shell. Why is that.
https://devblogs.microsoft.com/scripting/learn-how-to-configure-powershell-memory/
One of the things I like most about the UNIX userland is that I can use small programs to edit vary large files, without needing lots of memory. I want programs that are designed to accomodate the possibility of line-by-line processing.
If the intent is to make output network friendly, maybe something like netstrings is useful. Easy to parse. Low memory footprint.
Seems to me this JSON idea is not designed to improve performance, agility or resource efficiency but to ignore the UNIX example in favour of a different, slower, approach that is perceived as easier for some people to use. Namely those who do not want to spend the time to learn how to use an existing, faster solution with lower resource requirements.
I have seen that, and that's partially why it seemed so confusing to me but at least one difference is
The ForEach-Object cmdlet works much like the Foreach statement, except that you can't pipe input to a Foreach statement. For more information about the Foreach statement, see about_Foreach.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.3#notes
And another appears to be performance
PS /home/me> $time = (Measure-Command
{
>> 1..1E4 | ForEach-Object
{
>> $_
>> }
>> }).TotalMilliseconds
PS /home/me> [pscustomobject]@
{
>> Type = 'ForEach-Object'
>> Time_ms = $Time
>> }
Type Time_ms
---- -------
ForEach-Object 144.558
PS /home/me> $Time = (Measure-Command
{
>> ForEach ($i in (1..1E4))
{
>> $i
>> }
>> }).TotalMilliseconds
PS /home/me> [pscustomobject]@
{
>> Type = 'ForEach_Statement'
>> Time_ms = $Time
>> }
Type Time_ms
---- -------
ForEach_Statement 17.621
https://devblogs.microsoft.com/scripting/getting-to-know-foreach-and-foreach-object/
Every command has a short name.
A handy "punctuations" cheatsheet I found on reddit: https://www.red-gate.com/simple-talk/wp-content/uploads/2015/09/PSPunctuationWallChart_1_0_4.pdf
Short aliases for all major commands: https://devblogs.microsoft.com/scripting/table-of-basic-powershell-commands/
Some commands have more than one alias, and you can set your own, of course.
PowerShell also has a very nice help system. For any commands that Microsoft provides, you can type : Get-Help Get-ChildItem
It will list all the various parameters, as well as the various aliases.
As far as return values, you can do $? or type out $LastExitCode - it works the same way you expect.
For a fuller help view you can type "help Get-ChildItem" (all commands and parameters are NOT case-sensitive - it does not care if you type LS or ls, get-childitem vs GET-CHILDITEM does not matter). I prefer this - it helps in remembering.
For the third item in majkinetor's list, this is maybe one of the better explainers, with plenty of screenshots:
https://devblogs.microsoft.com/scripting/learn-about-using-powershell-value-binding-by-property-name/
If you pipe objects around between cmdlets, PowerShell will auto-bind object properties to cmdlet parameters. Which feels like the magic of the Unix pipe text streams everywhere but lets you skip several text parsers (no grep/awk/sed intermediates perhaps) and feels like even more magic when it just works: `Get-Process -Filter something | Stop-Process`. The blog post gets into some of the details of how it works and that it isn't just magic and that in PowerShell you can even inspect with tools like Get-Help to discover how it is doing it and use that to your advantage to automate complex tasks with very simple command lines.