Hacker News new | past | comments | ask | show | jobs | submit login
Jeffrey Snover and the Making of PowerShell (corecursive.com)
262 points by todsacerdoti 17 days ago | hide | past | favorite | 250 comments

Host here, thanks for sharing.

PowerShell faced extreme opposition at Microsoft, and its creator Jeffrey Snover was demoted for pursuing it.

Jeffrey was originally brought into Microsoft to help MS learn how to compete in the data center, but culturally they were so tied to the personal computer model of the world, that they fought him every step of the way.

Edit: Another interesting thing, is how Powershell exists because Windows isn't file based. Jeffrey's goal was server administration, but on Windows you can't just edit files to administer things, you need to call various APIs and get structured data back forth. The rich object model fell out of that. It was the only way.

( Also, apologies if the transcript has errors. I've gone from professional transcriptions to Descript and then a pass of GPT4 trying to find the right punctation breaks and then me doing a quick read through. I don't think its coming out as high quality as I'd like. )

If anyone from MS-PWSH team reads this, I'd love for y'all to add some basic GUI functionality that doesn't involve me having to write a bunch of .NET. I'm sorry, but the reason I like PWSH in the first place is it's a simple dynamic language with lots of easy to use commands that I can chain together. I'd love to have a new set of cmdlets for creating simple user interfaces and charts.

For example, something like the below would be so simple for Microsoft to add to the product and remove a page of boilerplate code that I don't really understand well.

Create-Chart -Type "Bar" -XAxis $Cities -YAxis $GDP -OutputFile "C:/Documents/ProjectAnalysis/CitiesBarGraph.png"

There are probably users in the millions that are ok at the basics of programming, but don't have the job role to where tools like Java or C# make sense. Python is usually a good fit here, but I really wish Microsoft had something written for us common folks and not just server admins and IT folks.

If Microsoft put some more effort into PWSH to where it wasn't turtle slow at things like parsing files and then started adding things like what I talk about above. Maybe even cmdlets for statistics and science...it could be something pretty amazing that your typical business analyst could quickly use to build some really amazing software to do their job better or a prototype for the software team to actually implement in a more robust manner. It's such a really cool technology that has a lot of missing potential IMO.

It seems like Microsoft assumes that the three options are full software developer with C#, IT stuff with PWSH, or Excel for the business folks. Excel is really great in a lot of ways, but it is also pretty limited and VBA+Excel is one of the most limited ecosystems I've dealt with. I guess third party languages like Python, R, and so on make for another fourth option, but sometimes I wish Microsoft had spent more time in this area.

There are some third party tools like PowerShell Pro tools or PowerShell Ultimate (https://ironmansoftware.com/). I appreciate they cost, but if you are a builder of tools for others, they really can help massively!

Thanks for the link. Yeah , I was aware of this one and another GUI builder someone sells, but it just really seems like something MS should provide as built-in. The ability to share a script to any windows computer without them having to download anything (exception being an old copy of Windows) and just run a program is an important piece in my eyes.

This immediately makes me think of TCL/Tk, back in the days where that was the lowest barrier to entry to get a basic X11 GUI app up.

TCL itself is very similar to PS in being a command based language, but it's a little weirder in some ways. It's nice and lightweight, but doesn't work with Windows as natively as PS, although I bet there are some COM or other libraries that can get you close.

The TK GUI is indeed lightweight, but a bit antiquated. I was thinking of something closer to Rebol, but maybe with a GUI builder as building a GUI with just Rebol syntax (although crazy powerful - Tetris is less than a page of code in Rebol) is a little challenging.

The main thing though is neither TCL or PS or Rebol covers everything I think is needed in a modern business analyst programming language. You need a simple dynamic language, ease of sharing programs, reasonable performance, really good OS interop, ease of building GUI, and a very large ecosystem of tools. Python is by far the closest here and is the programming language of choice for those in this segment for a good reason.

You are looking for something like Kusto then.

A query language? I don't think that's what I'm referring to at all if I found the right links. Business users can use SQL quite easily and tools like Powershell or Python make automating that easy.

Kusto renders graphs in your query results window

How is that relevant to my suggestion to have PWSH add in cmdlets for everything from GUI to chart/graphs, to adding scientific/numerical commands as well? I was talking about a general solution and not just graphs for my queries if that makes sense. I appreciate the suggestion though!

And as far as I can tell its no longer a priority at MSFT, reading the complaints from the MVPs on Github about how MSFT promised a bunch of further investment that has not been realized, changes not implemented, good stuff just sort of left to rot on the vine.

I loved powershell with (some of) its weird warts, but I have moved on.

There have been regressions even. PowerShell 7 isn't backwards compatible with PowerShell 5 and some features that used to exist are just gone with no plan for a return, due to (surprise) fights between .NET and Windows teams over API metadata formats or something. Most incredibly Microsoft situation ever.

Say what you want about bash, at least it doesn't pull stunts like that.

Wow, the Oracle chart is so spot on.

Always was ︻┳═一

(hey, I managed to sneak a rifle past HN's Unicode filter :-D)

As someone deep into Microsoft ecosystem since MS-DOS 3.3, it feels like the old ways of WinDev vs DevDiv politics have slowly creeped back into daily Microsoft.

It is as if DevDiv is now full into UNIX like, poliglot, FOSS culture and such, now under Azure business unit, whereas WinDev is back into how to sneak people into Windows licensing and the usual old culture.

Are there any currently-supported versions of Windows that don’t support Powershell Core? I recall installing it on Windows 2012, even.

> Say what you want about bash, at least it doesn’t pull stunts pile that.

I guess it depends on what you consider to be included in the terminal’s domain? There are entire papers and guides on which commands are considered safe (sometimes only when run in a very specific way), and which variants, alternatives, etc. you should use instead, for Bash scripts, because of the inconsistency in what a command evaluates, does, and returns for various distros. That’s not to hate on Bash, but just to point out that it’s not a strength of Bash vs PS.

When Powershell was first released I was primarily working with Unices and was very curious what would work better: The Unix way in cutting, changing and grepping some part of stdout (in some OS a bit simplified b with options for automated pricessing which commands the programm to output colon delimited or otherwise formatted)

Or the Powershell way where on can access data members directly.

I thought I would prefer the second method more, because the access looked much cleaner/structured.

But after all these years (still mostly Unix scripting but Powershell and some other environments too) my mind has changed.

Would like to hear what others would prefer' Unix method with some scripting language or windows method with Powershell)

Combining both powershell and unix is neat!

> The Unix way in cutting, changing and grepping some part of stdout

And this is exactly the problem.

You no longer have en_US as a locale? Have some titles lounger.

You no longer have en locale at all? Have an greška instead of error.

Oh, you the schmuk who don't agrees to use the best units in the world, totally retarded and "bUt iF yoU WriTe THe dATe as in the journal..."[0] but freedom ones? No longer accept 13 as an hour. Like come on, every idiot knows there is no such thing as an 13th hour!

Oh, you added an additional column to help your busniessor whatever? Your sEd MagIK gone to hell.

Should I continue?

[0] when was the last time you actually wrote multiple documents so you can actually benefit from MMM-dd?

> because of the inconsistency in what a command evaluates, does, and returns for various distros.

I'm not aware of any difference in bash between vendor distributions for which this is true.

It's less of a problem in today's Linux monoculture, but I actually initially learned Perl and Tcl precisely because of subtle incompatibilities between systems for tools like sed and awk, not to mention utilities like ps and tar.

This may not count because it's not bash specifically or even Linux -> Linux, but one place you might run into this is running scripts between Linux and Mac/BSD.

In the past I've seen bad things happen because a script was written by someone on OSX that gets run on a Linux (GNU) based system.

Two common examples are the `sleep` and `sed` commands.

Edit: I meant to reply to the parent comment.

My guess from external observations is that the reward and bonus structure inside Microsoft is entirely decoupled from customer feedback and response. The middle managers are in charge of the product and they're fully insulated from any concerns outside of getting this years maximum bonus for themselves.

Monopolies always destroy innovation.

I was under the impression much of that is due to the fact that PowerShell is Windows-only, while PowerShell Core is multi-platform.

They now refer to the former as Windows PowerShell, and the latter as PowerShell. The Core part was dropped.

It's easy not to lose features when you don't have many to begin with... I mean, what are the features that disappeared? What's the bash equivalent of these features?

For a programming language, losing a feature is much, much worse than not having it in the first place.

I'd like to see examples to judge. What are the features? Also, are you confusing "the language" with "the standard library"?

Years old existing code suddenly breaking because of an infrastructure update is just way worse than limitations when writing new code.

You can tell by WinGet which is a new product not even close to supporting anything PowerShell by design and almost being anti PowerShell with its overly verbose output. Which is odd since it's right up powershells alley being a management cli tool

If you have winget and powershell installed, try `Get-WingetPackage` and see what comes out. Or even better:

    gcm | ? noun -like winget*
    help Install-WinGetPackage
The "usual" winget cli tool is indeed not powershell compatible. But winget also ships with all the necessary cmdlets. You don't have to install anything extra.

The Winget module is a wreck. The way it is designed, unfortunately, neither fits the object oriented approach of PowerShell nor follows the PowerShell guidelines for cmdlets.

For instance https://github.com/microsoft/winget-cli/issues/3820 or https://github.com/microsoft/winget-cli/issues/3231.

Also, even though it does not completely work with PowerShell 5, it is marked as compatible. https://github.com/microsoft/winget-cli/issues/2881

The design choices made makes it weird. I hope it would be a good one in the future. But it is now problematic.

I was super excited to see this comment, but I don't seem to have those cmdlets, even though I'm on Windows 11, fully updated. Are you sure you didn't install something extra?

If I recall correctly, they only work in PowerShell 7. If you don’t even have them in there, you can install them from https://github.com/microsoft/winget-cli (which is bad UX, but if you just need them on one system it’s a way to do it).

I'm in PowerShell 7.4.2 and they're definitely absent. I hadn't thought to install directly from GitHub, given part of the whole shtick of winget is it's The One True Package Manager and bundled, but I can't say I'm surprised, either...

Probably better off installing from PowerShell Gallery instead. https://www.powershellgallery.com/packages/Microsoft.WinGet....

I don't remember. Maybe I did install the modules. https://www.powershellgallery.com/packages/Microsoft.WinGet....

    Install-Module -Name Microsoft.WinGet.Client

There is a Winget client module for Powershell. I used it the other day to write a one liner that could upgrade all with exclusions. I didn't want to pin, because I still wanted to see updates I'm skipping.

Does anyone even use winget? I tried but its repositories never have the tools I need in it. Scoop has been superior for me in every way.

UniGetUI (formerly WingetUI) is a really great tool since it supports multiple package managers.


I'm personally trying to use it inside configman running as SYSTEM and have gotten it working for the most part but I have not seen anything module based from Microsoft themselves.

Yes what I am doing can be done with intune but that's another story for another time. RIP Store for Business. I just want to deploy PowerBI and have it always be current and self updating.

I have found it useful. I used to install PowerShell 7.x, kubectl, Bicep (Azure language for deploying resources), etc. It works fine. The biggest problem I have is I cannot use it to install helm because the helm package is not shipped by the helm team (I don't trust packages shipped by third parties).

Have you asked the Helm team why they don't ship their own package? It might be worth the effort.

Yeah for the things they have its great, I've just found that they lack a lot of stuff. To this day they still don't have Apache Maven in the repository. I just use scoop, I've found that its repositories just have way more tools and it's way easier to contribute to.

I’m curious about the scenarios that Powershell used to work for you in, and what tooling you’ve moved on to. Do you use something else for Write-Once-Run-(Nearly)Anywhere type scripts?

I primarily write Powershell Core scripts for scenarios where I need to execute the same commands on a variety of operating systems, and I know that the script is likely to be maintained by your “typical” sysadmin (highly technical, but not a programmer)in an environment where installing runtimes for programming languages is discouraged. I switched to macOS as my daily driver about 2 years ago, so PS fits these scenarios pretty well, and Powershell Core updated fairly regularly. Sure there are annoying bugs and misses with the built-in and add-on MS modules: networking cmdlets are an almost total miss, Get-LocalGroup (and maybe other commands?) is totally broken on some AzureAD-joined machines, and the Azure and MgGraph Powershell modules still don’t have enough coverage to move on from the legacy Windows Powershell modules (or even to rely on just one of them, for areas they supposedly cover). But overall I’ve been pretty happy that 99% of the time I can write a powershell script once, and it will run on any machine with Powershell Core, in a consistent way.

Don't do as much "local" sysadmin stuff as most of the workloads moved to the cloud and containers, and that's all automateable via APIs which are much nicer to work with in python with its useful library support. (one of the biggest misses in powershell)

There's still a lot of good stuff wrt powershell maintainability by normal humans (though the entire mental model of object output usually throws them for a loop for years) managing local stuff.

PowerShell has the whole Windows OS libraries, COM and .NET available, without additional installation, a bit more than just Python.

Absolutely, and the calling conventions for all those pieces of code make no sense to powershell folks :)

If you have a background in windows dev or any of those tools then yeah, easy mode go grab your tools, but for most people doing system automation the calling conventions and complete lack of discoverability within the powershell ecosystem (and their tools in no way helping out) made this not a realistic use case.

Shoot I have seen some powershell modules that have to embed string C#s and eval thing just to have basic performance or other basic use cases.

The same challenge with calling conventions happens with Python calling into Windows APIs, moreso since there aren't that many wrappers available, other than installing something like ActiveState Python.

Right, but it isn't really a core benefit of using PS is my point.

It actually is, as it provides scripting across the whole OS stack and applications, closer to Xerox, Lisp Machines and Smalltalk REPL, something that no UNIX has ever offered, with exception of outliers like NeXTSTEP and OS X.

This is all technically true, but the thesis is that PowerShell makes it all horribly clumsy to use.

From the perspective of the Lisp Machine or, hell, even the AS/400, PowerShell (and, while we're here, the CLR) doesn't quite go deeply enough, pervasively enough, across the system to make it truly useful in the same way.

Extremely clumsy, yes. And not idiomatic - a vanishingly small people learning PS will be able to usefully discover, use, or troubleshoot this utilization.

At the very least they could have helped with the discovery/usage problem, but that would probably have been a really tall order for one little language to do.

Best I found is embedding LISP into .net


Not quite. What I'm more alluding to is something like, say, rewriting smss.exe and csrss.exe to be CLR programs (along with the implication of porting the CLR to the Native API) and giving PowerShell access to their internals directly.

IronPython also exists, although an older version of python.

For all practical purposes it is a dead project, sadly.

IMO PowerShell is very well integrated with Microsoft Azure cloud. Every Azure resource I work with (Storage, VM, Kusto, EventHub, Service Fabric, AAD, Networking) has tons of PowerShell support. I never set time to use Python with Azure Cloud - and this is only because PowerShell is so good at Azure.

I use Python for AWS, a lot. Last I checked, to use the Azure Python module you have to setup an Enterprise app, which seemed like overkill to me, and not something I think most of our sys admins would want to do. Maybe I’m wrong?

How is having the entire C# ecosystem a big miss?

It's a big miss for the casual convenience of a scripter/non-programmer. A Pythonic way to do a remote procedure call is XMLRPC (pseudocode):

    import xmlrpc
    svr = xmlrpc.connect('http://remote/')
    result = svr.add(1, 2)
The C# way is to use the Microsoft Windows Communication Foundation (WFC) Client Proxy using the Service Model Metadata Utility Tool and the Web Services Description Language (WSDL) and XML Schema Definition Language (XSD) files from the remote server, declare a public interface attributed as a Service Contract referencing a namespace, generate a class which inherits from the generic ClientBase<TChannel> and implements the new interface, create an instance of said WCF client and call its methods. (Or rely on Visual Studio magic to hide all that) - https://learn.microsoft.com/en-us/dotnet/framework/wcf/acces...

In any decision, Python goes for "What would Guido do?" and C# gets some union of "what would a committee of Microsoft, IBM, Oracle do?", "What would impress Gartner?", "What is Microsoft legally obliged to do, and backwards-compatibly required to do?", "What would we do if we tried to do everything everyone needs all in one?", "What would Java do?", "What would a large team need to design and maintain a stable, typed, large system for years?".

PowerShell is on top of that; there's no simple included graphing and drawing, no simple hooks into Windows own voice recognition and OCR, and definitely not into whatever magically good ones newer Office / Cloud is using, no casual email or spreadsheet handling, no Visual Basic style form building, no simple data science; there's a few things you can do or download, generally less convenient than a Python equivalent. And Microsoft are leaving it all 'to the community' but the community is using Python so that's where the Excel power-user who wants to script a couple of things will go.

I don’t think Python, a general purpose scripting language; and PowerShell, a shell, are going for the same things. They have different goals and by your definition every other tool is a “big miss” because they are not Python.

I have never desired to do xmlrpc, ocr, voice recognition, or gui building from my shell (and if I did I still don’t see how importing a C# library would be a big miss). What I do desire to do is open files, read their contents and pipe them into other programs, something that Python makes a pain to do with all the file handling. Powershell definitely excels at this, does that make Python a big miss?

I thought I was replying somewhere under this other side-thread https://news.ycombinator.com/item?id=40875610 which says "There are probably users in the millions that are ok at the basics of programming, but don't have the job role to where tools like Java or C# make sense. Python is usually a good fit here, but I really wish Microsoft had something written for us common folks and not just server admins and IT folks. If Microsoft put some more effort into PWSH to where it wasn't turtle slow at things like parsing files and then started adding things like what I talk about above. Maybe even cmdlets for statistics and science...it could be something pretty amazing that your typical business analyst could quickly use"

in that context C# library isn't fit for it. Yes I agree Python and PowerShell aren't going for the same things; that's annoying because PowerShell is 80% of the way there.

> "I have never desired to do ocr, voice recognition, or gui building from my shell"

I have wanted those things. Windows which has a built in speech recognition engine which is COM automatable, a shell (PowerShell) which can be a COM client, and I have a folder full of phonecall recordings. I have a folder full of photos with things like menus and road signs and I want the equivalent of strings.exe for OCR and PowerShell could almost do it. I've wanted to build a Delphi or VB6 or C# style drag-drop GUI and tried to do it in PowerShell with SharpDevelop, WinForms code, the ShowUI module. I've wanted to build a TUI but Windows console host isn't good at those. I've wanted to get jpg metadata out and done it with Shell.Application automation around Explorer instead of downloading mediainfo.

All these thing have something in common - a core in a low level language, glued together or scripted in a high level language. Microsoft have written the core. They have written the high level language. They just didn't bother to make it all integrated for the ordinary power user, or flesh it out with more features along those lines over the years.

> "if I did I still don’t see how importing a C# library would be a big miss"

Because, compared to a builtin "ConvertFrom-Speech" you have to be enough of a programmer to know you need C#, go looking for a package, navigate oneget/winget/psget/nuget/github to download it, worry about .NET version compatibility and module paths, work out how to add an assembly, and then deal with interop, [ref] parameters, byte arrays, streaming.

> "What I do desire to do is open files, read their contents"

Same. And the contents could be all common formats on Windows since the 1990s - MP3, JPG, Excel - things Windows can read and play, things Explorer can read metadata from.

> "and pipe them into other programs, something that Python makes a pain to do with all the file handling. Powershell definitely excels at this, does that make Python a big miss?"

Yes, I think PowerShell is a far more convenient REPL than Python's REPL. Than any REPL I know of, actually - within the boundaries of introspecting small simple data, PowerShell and .NET at least. And yet Python has set()-set() and PowerShell has [system.collections.generic.hashset[psobject]]::new().ExceptWith() (it doesn't return anything it mutates in-place) and every week, people post on the internet asking how to do essentially set union, intersection, subtraction and equality checks in PowerShell and the answer has been unsatisfying for decades.

Adding packages is `dotnet add package {PackageName}`. That's it.

Worrying about version compatibility for new projects has stopped being an issue. The package either targets NS2.0 or whatever latest LTS currently is, in which case you just add its reference, or it doesn't in which case you use something else.

If it does, in 98% situations it just works. In the last 2% it has native dependencies which means either a) the package ships with binaries built for all popular platforms, b) the package adds a platform-specific dependent package automatically, or manually and mentions that in README (either with dotnet add package or system-wide library, apt-get install and friends), or c) the package comes with windows only native dll, which happens with ancient unmaintained packages, it's a rare case nowadays fortunately.

As someone whose primary PL is C#, I found https://github.com/waf/CSharpRepl and https://github.com/dotnet-script/dotnet-script far more accessible and useful. Compilation caching for the latter works relatively well to make startup latency tolerable for using it for writing scripts over Python. It's not the smoothest ride, but the advantages of C# make up for this.

Or I just do `dotnet new console -o MyScriptName --aot`, echo code into Program.cs and `dotnet publish -o .` it. Some do that with Rust as well. Especially useful if you need your script to go through a lot of data quickly and parallelize that well too.

Completely missing the point.

"It would be nice if Microsoft polished the stuff they already ship so non-programmers could use it more easily"

"Well I'm a professional programmer (and I have installed a bunch of SDKs and tooling already) and I find all this trivial".

The state of .NET Framework package management is pretty much irrelevant, nor can be changed.

(and it was not that different from the UX above anyway, way better than e.g. Python)

Nowadays, WCF and even CoreWCF are frowned upon. Popular choices are gRPC, SignalR and JSON-RPC.

Heh... just wait until you get onto situation with a client machine/environment, open PowerShell and are faced with "Constrained Language Mode"...

> I primarily write Powershell Core scripts for scenarios ... in an environment where installing runtimes for programming languages is discouraged.

But PS Core is a programming language, right? And only installed by default on Windows?

I'm assuming there's other constraints on your system that make it preferable to installing bash or python on your Windows boxes?

My biggest gripe is that some Azure stuff seems to be available only through powershell, which is hard to install and configure (I think) in certain corporate policy-infested environments.

The Az PowerShell module just uses HTTP APIs, so anything they do can be done with other tooling if you really want to.

(There’s also the Az CLI tool, which I don’t like as much as the Az PowerShell module but might be easier to manage in an environment like that.)

Yes, true, they call APIs. But for whatever reason, MS decided that instead of documenting those APIs they went on the route of abstracting them in PS modules or the az-cli submodules that its mind boggling.

The REST API is documented. Maybe not completely so, but mostly.


Actually Azure CLIs are kind of schizophrenic, in typical MS fashion.

You have Azure Powershel Cmdlets (the old 5.1 based, and the new Powershell Core based), AZ CLI (in Python), AZD CLI (in Go).

The only one that offers full power is actually the AZ CLI one, e.g. some Kubernetes features aren't exposed in the others.

Yeah - and a number of Azure/O365 Powershell modules have long been deprecated. The promise of 1:1 Graph API replacements has failed to materialize for years now.

Is this a case of programming languages > shell scripts, or REST APIs the LCD?

The Azure CLI [0] is a viable method of managing Azure infrastructure if you don't/cannot use PowerShell.

[0] https://learn.microsoft.com/en-us/cli/azure/what-is-azure-cl...

If it exists in Powershell, it is backed by a REST API. Lots of AZ SDK's include a helper method to make calling the API's easier (like az rest cli command or invoke-azrestmethod).

What have you moved on to? I don't think I could go back to bash after learning PowerShell and no longer parsing string output.

Pretty much all python, dicts work just as well over here.

What have you moved on to? I have to use Windows at work and PowerShell is way better than basic cmd, even better with Windows Terminal. I suppose you could probably install bash or another unix-y shell but that seems like it wouldn't be as integrated with Windows.

As someone who prefers to read interviews and articles rather than listen, I really appreciate you providing a transcript. Thank you!

I wonder why they chose to build something from scratch instead of using python or similar tools that existed before.

Something like ksh, you mean? Like they talked about in the article?

Because .net was the center of the whole ecosystem

> I've gone from professional transcriptions to Descript and then a pass of GPT4 trying to find the right punctation breaks and then me doing a quick read through. I don't think its coming out as high quality as I'd like.

I tried reading the transcript and couldn’t reach the end, it’s a bit hard to read in my opinion. I assumed it was machine generated while reading it, but I can’t say why specifically. Maybe it needs a bit of editing to be easier to read.

Thanks for the effort anyway, it’s still better than no transcript :)

Its funny, because professional transcriber will get the same words. But with better choosen paragraph breaks, and sentence splitting and dropping filler words where it hurts readability.

Hard to get right, it seems.

> the transcript has errors. I've gone from professional transcriptions to Descript and then a pass of GPT4... [...] I don't think its coming out as high quality as I'd like.

I wondered why there were so many unintelligible passages. I found it laborious to decipher. Thank you for explaining.

>PowerShell faced extreme opposition at Microsoft, and its creator Jeffrey Snover was demoted for pursuing it.

That makes me sad. The dude is absolutely brilliant.

Awesome post!

That was a great listen, thanks.

I've always been curious to know. I am an experienced Bash developer, and when PowerShell was released, I was very excited. Finally, we would have a cool shell on Windows for development. However, since then, I've never managed to grok PowerShell and continue to use my good old Bash even on Windows.

What is the experience of other developers who are experts in both shells to compare them? Did PowerShell really fulfill the promise of being a more efficient and modern shell? Or people just use it because it is already installed and better than CMD?

I've done a lot of Bash, read some books about it, I'm a firm believer that nobody should be writing anything complex in bash. Above the ballpark of 50 lines I consider it a code smell. I have this web page saved up in case I ever need to convince anyone of this.


I used Powershell recently and not having to wrangle with text (commands return objects) makes it a much easier scripting language, and command line language.

The fact that they have an official way to handle argument parsing is excellent, everything is unified and the commandline window is able to have autocompletion for literally every option of everything. Bash could never even dream of having that. It is incredible and makes you extremely productive.

But type coercion manages to introduce new ways to create bugs that Bash didn't have.

Honestly at this point I prefer PWSH but still kinda dislike both. I'm waiting for the new natural evolution.

> I have this web page saved up in case I ever need to convince anyone of this... http://mywiki.wooledge.org/BashPitfalls

This is a great list of pitfalls, absolutely, but they are more an argument for integrating shellcheck into your IDE than avoiding bash, IMHO!

I know, I know, possible religious war, but I find that bash+shellcheck is far more often the right toolset than switching languages to avoid the pitfalls.

The immense power and expressiveness and immediacy of bash makes so many programs and so much prototype->PoC->MVP progression so easy and effortless that it is worthwhile having tooling to catch the worst of the warts.

Add shunit or similar and I You can have a really nice experience (imho).

I don't know if I agree with that. I write Bash; I've written some stuff I really shouldn't have written in Bash. Writing elegant Bash is possible, though I agree it is very easy to footgun yourself with it. The problem is that Bash is right at the middle of "I need something quick" vs "I don't want to break out Golang or whatever" and Bash is installed damn nearly everywhere.

A 50-line awk script though? Get outta here with that lol

I don't trust myself so I need my language to not be bug-prone

(and I don't recommend it for others because if we're looking at it realistically, most people who trust themselves shouldn't trust themselves)

Shellcheck is amazing at preventing bugs!

Do you write unit tests in other languages? Do you write unit tests for your bash scripts?

Yes, if the "script" is big enough. I use BATS for that.

> I don't trust myself so I need my language to not be bug-prone

Which language is that?

it just isn't everywhere though. sh, ash zsh, Mac... windows are all different. you think it works everywhere but really its just breaking and nobody is telling you. python is just as everywhere and that's a total mess.

I totally agree. Bash is an absolute nightmare to program in. Just an utter mess of a language, one which I avoid if at all possible. Whereas powershell is an actual sensible language. I love writing it, and honestly I wish it was popular enough in *nix land that I could feasibly use it there too.

Well, there's nushell, which probably integrates better with *nix than pwsh, although it isn't popular either

Many of these pitfalls are not the shell, but external programs (sed, xargs, grep, etc).

I know it ends up in the same terminology bucket for the public consciousness as "CLI stuff", but there is a separation and understanding this separation is crucial for writing good sh.

The problem actually lies in bash+coreutils being some sort of de-facto standard for command line stuff. The way bash+coreutils evolved was mostly for autotools and not for humans. This ecosystem could be much better.

PowerShell has more builtins, so it relies less on external commands, therefore it is less vulnerable to pitfalls due to mismatches between different programs.

For mismatches, custom scripts & commands in Powershell benefit from having a standard way to take input, and because the output is not text, you're also safer on that end

But in the end really it doesn't matter in whose end of the kingdom the bugs come from. What matters is that's how people write Bash.

It works very well if you're all inside powershell.

Try this exercise: make a .BAT invoke a powershell script that invokes another .BAT passing parameters containing double quotes inside. It just can't be done reliably. The .BAT is only just an example, any param passing to/from powershell (outside powershells internals) is a nightmare.

In bash, this kind of interaction is commonplace. You can make `find` generate shell snippets for you, and pipe the generate shell commands into another interpreter instance seamlessly.

Think of the sheer amount of software the uses the shell this way and you never notice. That npm script that just passes parameters along is relying on the shell interface, that CI yaml that passes variables is relying on the the shell interface, etc. It runs just for a few milliseconds, to pass and glue things around, super simple. Powershell is just not designed nor suitable for that.

The problem of an uniform interface _can_ be solved by changing how people write stuff. The problem of not fitting well as an architectural piece replacement is much more difficult to overcome. Powershell fits Windows though, but that's about it.

Powershell passes data not instructions and a lot of those complaints sound like trying to write another language in Powershell. I've shoved json from node through Powershell into the clipboard and back to filter with select-object and out. the situation making you invoke bat at all is what MS ruined and that's not Powershell fault.

Technically it's Windows' "here's a string of the commandline, go parse it yourself" (vs. argv array) that's the issue as every program can interpret quoting, escaping etc. differently. All these programs being from MS (powershell, cmd) does make them a little guiltier I guess.

It's not me deciding to mix bat and powershell, and it's not niche:


There's a need for a fast, nimble glue that powershell can't deliver on its own.

This is what I meant, these are all examples working around the default execution policy. That's microsoft ruining things not powershell as a language. I didn't say it was niche rare or wrong. It's just bad and it's MS's fault.

I forgot but one thing I also liked that made me go "Why would bash not have that?" is having a dedicated verbose,info,warn,error,debug output and a glob star *> to redirect everything. It's nice not having verbose text polluting stderr.

I’ve spent so much time wrestling with and learning all (most) of these pitfalls, and I consider it time well spent. After my first few weeks I started dreaming in bash.

PowerShell is more verbose than Bash, and has its idiosyncrasies (like sometimes automatically unwrapping 0/1-element arrays into scalars when you least expect it), but it is more productive and more readable. Object-orientation can be nice to produce pipelines.

For example: find potential file duplicates in a folder, recursively, by grouping by file size:

    Get-ChildItem -File -Recurse | Group-Object -Property Length | Where-Object { $_.Count -gt 1 } | Sort-Object -Property Count
No need to remember arcane `file` incantations, no need to parse textual output. You get real objects with properties, and tab completion can see their structure.

Need to parse JSON? No need to involve `jq`, just `Get-Content -Raw whatever.json | ConvertFrom-Json` and do it directly from PowerShell. Need to convert XML into CSV? ConvertFrom-Xml (or Select-Xml) -> do stuff -> ConvertTo-Csv.

Is `Get-ChildItem` too much typing? Use `gci`, or `dir`, or `ls` (by default only on Windows). Is `Where-Object` too much? Try `where` or `?`. And things are case-insensitive.

You can even simplify your `Where-Object` as

    ... | Where-Object Count -gt 1 | ...
Or, of course,

    ... | ? count -gt 1 | ...

...and how do I get a "manual page" for the command "Get-ChildItem" in the console?

You can use "man <command>" the same as in nix. The man command is an alias for Get-Help and it retrieves the same information.

There's a lot of nix aliases for Powershell commands. Get-ChildItem is also called with ls, mv calls Move-Item, cd calls Set-Location, etc. They made at least some effort to make it more accessible to people coming from *nix or cmd.

Get-help get-childitem

Also remember to check Get-Help Get-Help.

Also, unfortunately, you'll probably want to Update-Help first, because for reasons beyond my comprehension, PowerShell does not ship with detailed help installed by default.

I started my career with a X term hosted on a SunOS pizza box, have written thousands of scripts, more than a few in the KLoC count.

Several years ago, I had to write a complex unattended robust data transfer system in PowerShell. (I know, I know, without more info these “requirements” beg many questions, but they are all out of scope for this reply.)

I enjoyed the experience so much I switched all my shells, on MacOS (my DD) and on Linux (my most common work environments) to PWSH.

What I liked most about it was the power of passing objects in pipelines, and being able to extract/manipulate some of the properties of an object in the first filter and still have access to others, along with those of objects created by that first filter, in filters later in the pipeline.

Immensely powerful.

The consistency of commands, of error handling, and of object properties was also very nice.

Eventually, as the nature of work changed I switched all shells back to bash, as the older muscle memory asserted itself. PWSH as a shell made sense when I was working and thinking so much in that space, but when I left it, it was more effortful to think in PWSH than to resume bash.

There are times I miss it. There is nothing else in the shell space that comes close, or at least not close enough to justify the effort of switching.

a few years ago I had to write a data integrity check for tens-of-thousands of files. Just crawl the dir and compute filename, size, checksum, maybe date, can't remember. I thought "ooh neat, I bet I can use some powershell trick to compute that tuple for each file", and no. Immediately ran into some obscure limitation with their "pipe" - I can't remember the details, it was like impossible to create many-things from a single-thing - and thought "how disappointing. the one time I give it an honest shake to do something entirely conceivable by the creator and it falls flat on its face.".

Nothing in your description sounds difficult to do in powershell. You can certainly output "many-things" from a part of the pipeline that takes "single-things" as input. Crawling files is a single command, then you can do whatever you want with each one in the next part of the pipeline - "map" from file info object to something else (e.g. custom object with filename, size, checksum, etc props) 1-1, multiplex each file into N output objects, buffer file inputs until some heuristic is met then emit outputs, etc.

A lot of years ago, circa Exchange 2010, there was a limitation on pipelines-within-pipelines which had to be worked around. Files already include name, size, dates, so select all of those and add a calculated property of the file hash using Get-FileHash (MD5 and SHA options):

    gci | select *, @{L='Hash'; E={ ($_ | Get-FileHash).Hash }}

    Get-ChildItem | 
      Select-Object -Property FullName, CreationTime, Length, 
                              @{Label='Hash'; Expression={ ($_ | get-filehash).Hash}}
but even then you could do what you want with a traditional loop and no pipeline:

    $results = foreach ($file in get-childitem) {

        # a hashtable of things you want to be
        # in each object ('row') of the output:
        $data = @{
            Name   = $file.Name
            SizeGB = $file.Length / 1GB
            Hash   = ($file | Get-FileHash).Hash


Thanks for taking my belly aching memory and being constructive. I just vividly remembered the sour grapes taste but I guess it was just due to my incompetence. I think what I didn't know was how to do the nested sub command for Hash. Cheers

Do you remember what the common commands for pipelining you used were?

I feel like my PowerShell struggles are really about not knowing 2-5 core, general-purpose pipelining commands well enough to use in any situation.

Not OP but the "-Object" commands are pretty fundamental to creating useful pipelines:

Select-Object - Pick out specific fields from an object, create calculated fields etc.

Where-Object - Drop non-matching objects from the rest of the pipeline.

Group-Object - Cluster objects into groups based on a shared property value.

Sort-Object - Order an array of objects based on a property value.

Get-Content - Read from a file.

ConvertFrom-(CSV/JSON) - Parse a json/csv formatted string into a powershell object.

ConvertTo-(CSV/JSON) - Serialise a powershell object into a csv/json string.

(Parallel)ForEach-Object - Loop over each item in the pipeline, performing one or more actions on it. Usually occurs at the end of the pipeline, or when you need to call an executable that can't handle pipeline input.

One thing I struggled with in the beginning, was not knowing what properties an object might have. You can pipe any object into `Get-Member` and it'll list its available properties and methods.

Many of the "-Object" commands support the use of script blocks if you need to carry out more complex filtering/projection.

Thanks for the detailed write-up! I'll give them a try today.

    |? PropertyName -gt 5            # where-object filter numbers
    |? PropertyName -match 'text'    # where-object filter text
    |? {$_.thing ...}                # where-object filter script

    |% PropertyName    # same as select-object -expandproperty propertyname
    |% { $_.thing }    # foreach loop
    |sort prop1, prop2
    |sort {$_.Name.Substring(0,5) -as [int]}   # sort calculated thing

    |fl *        # format-list , all properties
    |ft -auto    # format-table, autosize table column widths

    |sv q        # set-variable -name q, same as $q = <...>
    |tee -var q  # same but show the results as well as storing in q

Helpful! Thanks!

Others have provided better answers than I could have, as I don’t remember clearly enough.

What I do remember is that until I understood what I was trying to do and why (mostly error handling around edge cases, all specific to the app), I couldn’t really grok the various object management calls, but that once I’d done a few rounds of PoCing and RTFMing, everything fell into place.

Get-ChildItem, Select-Object, Where-Object, Sort-Object or anything that is operating on a collection feel very natural. Often times I'm piping Get-ChildItem into sort to find the most recently created file in a directory.

No expert in either but I've had to use both a fair amount. Powershell fell into a few traps that rendered it awful to use IMO:

* Trying to be a .NET language. I don't know why the one-runtime-many-languages promise of .NET withered on the vine while it flowered in Java-land without the promise even having been made, but it did. If you're writing .NET code, use C#. (And I say that having worked in one of the very few teams doing large scale development in F#.)

* Failing to get the basics of being a shell right. I can't remember the details as I've left it firmly in the past now, but its handling of redirection was just broken, to the extent that things that were trivial in bash were nigh on impossible in powershell. I got the impression its developers ignored the things bash etc. did well in their enthusiasm over building something new and powerful.

* Being fetishistic about stuff like requiring Verb-Object naming for everything. It's certainly subjective and has its defenders, but IMO it renders scripts ugly, is awkward to type and doesn't materially improve discoverability or memorability at all.

PowerShell isn't quite a .NET language, and you can't really write serious .NET software in PowerShell. But if you need to access the power of .NET (or heck, COM) from a script or an interactive shell, PowerShell lets you do that.

That's the point, though. It's a bad .NET language, but the desire to interact with .NET dictated much of its design. Windows didn't need a way to "access the power of .NET". It needed a decent shell, and sadly still lacks one

Edit: And that isn't to say .NET doesn't need a scripting language. It sorely needs that and the various relatively useless variants on "C# scripting" are testament to that. Powershell isn't, and doesn't even attempt to be, a solution to that lack, though.

To be fair, nothing in .NET required Powershell to make the choices it did (case in point: F#, ClojureCLR) for the integration. I wish to learn it but it being so...wordy definitely makes it an unattractive choice. A shell should be terser than F# or C#, not the other way around.

Yeah, "dictated by" is probably the wrong phrasing. A decent shell with those capabilities could probably have been made, but I do think the drive to make something fancy and new based on .NET was a big part of the reason they neglected decades of insights and successful idioms in the shell space, which were sorely needed on Windows.

>decades of history and successful idioms in the shell space

Just because something has persisted for a few decades does not make it good or worthy of being emulated on a platform different from the platform it started out on.

I don't recall saying that it did. My judgement that Windows needed (and still needs) those ideas is based on heavily using both platforms.

I just gave up on Windows. On every step it feels proactively user-hostile, with non-dismissable notifications, removal of UI customizations, constant reminders to change some settings to "recommended" despite my choice, accompanied by overall loss of reliability.

It feels like there is no more vision, desire and engineering excellence left in the teams responsible for it. I know that there are rare exceptions like Microsoft Store that, as an application, has started to work so much better because the person responsible for it cares, and it uses WinGet for updates and distribution, which is great. But these are droplets in the ocean.

At this point, setting up a Linux distro for a desktop yields incomparably better experience given equal amount of effort.

The only thing that makes me worried is that such a dismal state of affairs damages the image of .NET which is night and day compared to most other products made by MSFT in terms of quality and taste, it already needs help - note how much undeserved good will Go and Swift receive, despite former being much worse than everyone thinks once you look into the fine-print and implementation details, and latter having poor non-macOS support story and ecosystem outside of iOS development. And at the same time no matter the degree of improvement that happens to .NET, it is popular to bash it, even if the criticism is completely detached from reality.

(downvotes only demonstrate my point)

The article is about exactly this. Powershell's job was not to be a decent shell, but to make server management work automatable. Unix style shells didn't solve this because windows was not file based, you need all these hooks into these various api to setup a user, or a network connection or a whatever.

Why it's .Net is also covered and its probably not what you expect.

The odd part is that, at its core, Windows still is file-based. Managing it isn't, but anyone who's gone digging around in NT's Object Manager will be familiar with using CreateFile() to get a handle for manipulating things there.

It's, in fact, pretty pervasive when interacting with Windows programmatically, just as it tends to be on Unix-alikes, and the fact that PowerShell doesn't do well to acknowledge that is frustrating. (Worse, Windows is a better Plan 9 of sorts with MIDL and COM everywhere, and PowerShell falls pretty flat here too compared to the experience of, say, slinging a dynamically generated command stream directly at fossilcons.)

Yes, I could break into C# or C++ for this, but that takes the tasks that rely on these operations firmly out of the hands of paraprogrammers.

Eh, I find PowerShell nicer than bash. And having a way to use .NET/COM stuff ad-hoc can be useful in scripts. For example, to talk to Windows Installer with reasonable performance over COM. Or to launch the best browser:

    (New-Object -ComObject InternetExplorer.Application).Visible = $true

As someone who really likes F#, I wonder sometimes if I should just jump ship to ocaml or Haskell. What made you feel like F# wasn’t ultimately worth it?

I don’t like powershell because it’s so surprising in a billion ways from bash. The tab being replaced with right arrow screws me up, and so does not having the normal commands, and it’s quite opinionated about naming.

That said, powershell seems more capable than bash if you know it well, because it has a better type system and arguments are easier to mess with, whereas bash things are amorphous strings.


That’s a slightly out of date version of what I use to provision stuff on my windows machine to test things, and can show what’s possible a bit.

I find it is in a weird spot where it is more powerful than bash but you often don't need that power or if you do coding in c# might be better.

It is very good of you want to work with Azure though. You probably don't want to use bash for that. But lots of reading up each time I use it. Bash is my go to for small jobs or a command line experience.

I am not an expert in either but have used both plot to get stuff done.

Most times if I’m doing anything suitably complex it ends up as a little C# app rather than powershell.

I used a Powershell-script in a recent project and learned some lessons. It gets some data from an API. It is run dozens of times every minute, can run concurrently with itself, has some writing to a json file cache in a race condition free way. Works mostly ok. Development has been difficult because of low volume of forums talking about Powershell. Wouldn't have bothered to make the script without ChatGPT. One time it failed by inexplicably setting system+hidden+read only flags in a project folder. Quite a head scratcher. The worst experience was a bug I still don't understand: The script failed to get an access token when running in "ordinary powershell" but managed to do so when running in Powershell ISE. I checked every possible environment difference and concluded that there was only one: powershell.exe vs powershell_ise.exe. I am not going to be making any more Powershell scripts.

Well I used powershell a lot when I was managing VMWare infra. Ultimately the force of a object oriented shell is in the ecosystem, I haven't found any other use case where powershell was useful to me. I am pretty sure it is useful in an Azure context too but in the last few years I have never been in a situation where I would feel the need to install powershell on my linux workstation to use a specific module/use case.

Powershell is a huge improvement over cmd. However; much like Windows, it is full of complicated gotchas and edge cases. Bash has them too, but Bash makes concurrency and parallelization extremely simple, so despite it's absolutely bananas syntax and rules for hash tables and arrays, it is superior IMO. Bash also makes it simple to write your own more complex utilities in any language and call them from bash. Linux makes it simples to implement new kernel tech and Bash makes it simple to interact with the kernel.

Windows... You have to wait until someone in WDG decides some existing idea is good and then also wait for them to get support to implement the idea, then wait to see how that whole thing goes. So yeah Powershell is great for interacting with Windows. But Windows thinks you're a dumb shit so you can only do what Windows already lets you do.

I was extremely well versed in PowerShell early into its development.

It was indispensable when it came out. VBscript and Cygwin were the only options; both of them sucked. The ability to use native .NET objects in scripts was insane; I definitely abused that!

Nowadays, Git Bash and WSL2 replace a lot of the value that PowerShell provided.

It's purpose was to drive Microsoft away from the GUI, and, at that, it more than succeeded.

> VBscript and Cygwin were the only options; both of them sucked.

I'd challenge the Cygwin aspect. With judicious use of cygpath & co., you can go VERY far with Cygwin. I've built an entire SaaS deployment system on top of it (and Python).

A shell is not a thing by itself. It's only as good as it integrates with the rest of the system.

So, the experience of PowerShell on Windows is unbeatable... on Windows. It's easily beaten on any other system.

I use *sh at home, and Powershell at work. Powershell has a lot of really cool and genuinely useful concepts. There's the obvious like piping objects instead of raw bytes, but there's also things like first class parameter validation, automatic array flattening, multi-threading, full .NET API interoperation, and more.

Unfortunately, it also has some real sore points for use as an interactive shell, and even some outright broken behavior. Some that I lament most frequently:

- Powershell has native tab-completion support, but the word-of-god dictated "Verb-Noun" command naming scheme means almost every command shares a common prefix with a slew of entirely unrelated commands, making tab-completion painful.

- Power shell has sparse built-in support for funtional style list manipulation or data structures beyond lists. There's a "map" command (%), but no reduce, zip, tail, etc. These feel like they'd fit in perfectly to the design of the language, but they're just missing. Also, pipes are lazy, but lists are always strict, which can cause friction.

- most operators are strangely named, such as "-eq" for ==, which hurts legibility.

- There're lots of unvoidable brackets, meaning you often need to jump around the line while writing out a command incrementally. For example, to get filenames, you either need to write `(Get-Item).Name` or `Get-Item | %{$_.Name}`. It'd be nice to have something like `Get-Item |. Name` as an option.

- It's impossible to pipe raw bytes between commands/executables; raw bytes are interpreted as strings. This means, for example, it's impossible to pipe a file to `patch`, because the contents will be decoded into strings, piped as strings, then re-encoded with line endings changed, which `patch` rightfully refuses to apply.

- Running Powershell scripts is disabled by default (WTF?)

By comparison, *sh's heavily favor interactive use. For example, you can put io redirections at the start or end of a line, tab-completion is often very good, it's often possible to avoid brackets (ex. with xargs), background/foreground job management, etc.

Overall, I often find Powershell more pleasant to use than *sh, especially when writing scripts. But for interactive use, I often wish Powershell was a little smarter and a little dumber at the same time.

Why is automatic array flattening a good thing? This has caused more bugs than I can count. Every time I make an array I have to check if it has a length of 1 and do something special with it or else the script blows up. Best I can tell this is a huge foot gun anti-feature. What am I missing?

It's a foot gun, and the behavior is often surprising until you get used to it and sometimes after, but Powershell would be very painful to write without it. Basically all functions return a list in Powershell, including all user-defined functions, so you'd need to unwrap singleton lists all over the place.

But if they COULD be lists of >1 then by unwrapping it you have two scenarios to handle instead of one. How is this an improvement? And if it is ALWAYS a list of one why return a list?

All Powershell functions are basically python generator functions. It could have been designed to have more traditional functions, but I find generators fit well into a language based on piping streams of values between functions.

Usually, the distinction between a single item, a flat list, and a list of lists isn't important in Powershell, because commands are written with Powershell's behavior in mind. It's extra painful when it does matter, but it's a trade off against being more verbose every time it doesn't matter. Ultimately, it's personal preference; for an interactive shell, I like the tradeoff Powershell made, and I think it's a cool design space to explore, but I do think there's a lot of room to improve the implentation of the concept to make it less surprising and less painful to choose the alternate behavior when needed.

This works:

    Get-Item | % Name

Welp, I wish I'd learned that earlier.

I switched to menu completion and the tab completion isn’t as painful with all the choices.

I have used it for nontrivial stuff. The idea of streaming objects has a lot of potential, but I think the "enterprise crowd" had a really good crack at it - especially the syntax. Not having to resort to grep, jq, cut, and the host of tools required to (often fragile) parse out whatever specific format the tool you are calling is giving you.

Put another way, you could feel free to parse the output of ls in powershell - because it's already been done for you.

They should have called it PowerScript, because it's a perfectly decent scripting language and an absolutely horrendous interactive shell language.

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...

I just find everything about powershell tricky. Something just doesn't click for me. It's always a struggle.

Exactly my experience.

It took me about a decade to be comfortable with it :)


> GUI by their very nature usually make "simple things easy, and difficult things impossible".

Creating an Active Directory forest was traditionally done via a GUI wizard. I would say that makes a very complex task easy, where-as creating it via CLI requires some amount of knowledge, making something otherwise easy "difficult" as you need to know what the CLI parameters are asking for (GUI explains it in plain <localized language>), _and_ you need to know what the proper cmdlet is, leading to difficulty in discovery.

Server Manager starts automatically after logging into Windows Server for the first time, presenting the user with a two-click method to start the deployment of AD (and some more clicks for the wizard itself). This lets anyone, from an SMB one-person shop to the largest company in the world (who is that?) deploy AD in a matter of minutes. It's empowering.

Equating Win Admins with chickens is rather disrespectful and/or elitist. "Don't get mad, bro!" doesn't absolve one of their statement.

I've written PowerShell modules in C# for SharePoint Server. I continue to use the click-click-next-finish GUI for certain tasks. Does that make me a troglodyte?

[0] https://learn.microsoft.com/en-us/powershell/module/addsdepl...

The point was things like AD are not really transparent to the end user, and thus difficult to handle in a CLI outside of a utility (usually need privileged MS insider OS API documentation). As a side note, exposing a desktop environment in a server role is still a problem 30 years later (GUI usually slowly leak memory over time.)

Note chickens are fairly aggressive little creatures, and through the power of Cortana could easily masquerade as an admin. Thus, one has to be careful when you see sharp peckers.

Have a wonderful day, =3

> thus difficult to handle in a CLI outside of a utility (usually need privileged MS insider OS API documentation)

There's a CLI command for it! What are you talking about with regards to APIs needed to do the particular task I mentioned?

> (GUI usually slowly leak memory over time.)

No, no, no, no. Please don't make up false statements to try to "prove a point".

You're just being disrespectful to be disrespectful. You're disrespectful of many talented individuals in the industry. For shame.

Powershell wasn't awful when I wrote it but I never understood why arrays of length 1 removed the array and become the contained type. This caused a huge # of bugs as you suddenly had to care how many items could potentially be in the array and check each time you modified vs. handling them generically. Does anyone know WHY they did this?

There's looseness around arrays because the API for emitting outputs from commandlets is also loose around arrays. There is just one function `WriteObject` that writes the value you give it as the output of your commandlet. If you call it once, then that's your output. If you call it multiple times, then the shell has no choice but to then make your output an array of all the values you write.

So if one invocation of your commandlet only calls `WriteObject` once and the other calls it twice, the shell in the first case doesn't have the knowledge that it should've wrapped that one output in an array too. And it can't always wrap commandlet outputs in arrays because that would be disruptive for commandlets that semantically only have one result and so always write only one output (like `Get-Date`).

And for whatever reason, they didn't want to complicate the API to let commandlets themselves be able to express whether they'll semantically write only one output or multiple, regardless of how many times they actually call `WriteObject`. Such an API can't be a static attribute on the commandlet because commandlets can have wildly varying output based on their parameters. It can't be an overload of `WriteObject` like `(Object, bool iMightWriteMoreValues)` because it has to work for empty arrays. So it would have to be a separate `IWillWriteMultipleValues()` function probably.

Edit: Also explained here: https://news.ycombinator.com/item?id=40874873

This is so annoying. I’ve started using the preceding comma hack to force an array.

  $Ary = @(, "value")

One cool feature for creating arrays (especially larger arrays, for performance improvements over using +=) is to assign your array to a for loop. It wasn’t an obvious method of populating an array to me, but is definitely handy.

  $Ary = foreach ($Obj in $Objs) { @{ foo = $Obj.foo } }

I think @("value") is enough.

I use

    [array]$Ary = "value"

I haven't used PS in many years, but I do remember `@("value")` would still end up unwrapping the single-element array back into its element in some situations, and the only sure-fire way to get an array was `, "value"` or `@(, "value")`

> Does anyone know WHY they did this?

That sounds like a classic case of software trying to be "too clever," nine times out of ten of which will invariably backfire.

As a software developer, one should always resist the temptation to make their software "too clever."

Agreed. This drives me crazy. You have to work around it in a script of any complexity. It's probably my least favourite thing about PowerShell.

It feels like a half baked feature. The other (missing) half would be automatically converting a single value into an array of length 1 when the receiving end expects an array.

Niche languages seem to end up with insane quirks like this every time. It's like the tragedy of sisyphus that things like lua exist, but instead of using it directly or modifying it slightly, then having a dead simple, tight, small, elegant, consistent language, people reinvent the wheel and never make it round.

Lua is not perfect either. Having a specific keyword to make variables local was a mistake. Variables should be local by default. Oh, and 1-indexed arrays are annoying.

Both of these could be changed trivially. Someone familiar with lua could do both in one day as opposed to making an entire brand new language from scratch.

This is reminiscent of MATLAB where there is no distinction between a scalar and a 1x1 matrix.

A scalar _is_ a 1*1 matrix

A scalar however is not a tuple of length 1

Unless I'm interacting with some Windows subsystem, and need the specific Powershell commands, I just think "why the fuck am I not using Python?"

It's also way too verbose and slow for 90% of the stuff I'd use Bash for (or would have used Perl in another life)

I often wonder why Microsoft didn't base it on Python, Node, or something else. I can't remember when PS was first released so I'm not sure what would have been ideal at the time.

Python's default REPL is godawful. It's also just not designed for the kind of console work that PowerShell excels at because you have to do things like managing file handles rather than just getting the file content and piping it to another command.

PowerShell is great because it's a swiss army knife that has a very nice REPL with autocomplete, no weird whitespace behavior, readline[0], and can do anything .NET can do if you need to do anything more complicated.

Plus it's object oriented so you can focus on doing the tasks you actually need to do rather than trying to figure out how to use archaic utilities to parse the text based output of other archaic utilities.

0: https://learn.microsoft.com/en-us/powershell/module/psreadli...

>> I often wonder why Microsoft didn't base it on Python, Node, or something else. I can't remember when PS was first released so I'm not sure what would have been ideal at the time.

They originally based it loosely on Perl and the Korn shell. In the first edition of "Powershell in Action" by Bruce Payette there is a sidenote that states:

'PowerShell uses the "at" symbol ("@") in a few places, has $_ as a default variable, and uses "&" as the function call operator. These elements lead people to say that PowerShell looks like Perl. In fact, at one point, we were using Perl as a root language, and these elements stem from the period. Later on, the syntax was changed to align more with C#, but we kept these elements because they worked well. In Perl terminology, they contributed significantly to the "whipupitude quotient" of the language.'

It also states:

'The core PowerShell language is based on the POSIX 1003.2 grammar for the Korn shell. Originally, Perl idioms were appropriated for some of the more advanced concepts such as hash tables. However, as the project progressed, it became clear that aligning PowerShell syntax with C# was more appropriate.'

Powershell predates Node by 3 years.

They probably didn't base it on anything else since they control .NET.

I doubt it's slow because of .NET, it's slow because of either its design or because of under-investment in performance.

However... which version of PS are you using? As far as I remember the newer versions are quite fast.

At $dayjob I am blessed with the task of wrangling a 20+ year old codebase of SQL Server stored procedures. It's around 300k lines of monkey tested, business-critical code that:

* wasn't source controlled

* was never tuned (properly) for performance

* deployed into environments by editing/executing sql in SSMS.

* of course, no automated tests, etc...

It's a windows shop, I am developing on a Mac, and we do linux on Github Actions.

I selected tools like PowerShell Core, sqlcmd, docker for running Windows SQL Server instances, RedGate SQL Compare for extracting existing schema and code from the legacy servers, tSQLt for unit testing, TSqlLint for code compliance, SQLFluff for style compliance, and Flyway for deployments.

We quickly discovered PowerShell Core was the most interoperable cross-platform scripting shell when Windows had to be one of the platforms.

It wasn't pleasant to code in. The regex engine comes from .Net, which has bad catastrophic backtracking problems, and the array situation was goofy. Launching executables with any sort of control over the launch and capturing the output stream was hit or miss - I would often have to launch a process, redirect its output to a temp file, and then read the temp file after the child exited. So piping around with child's stdout into a string variable was always more trouble than it should have been.

BUT, PowerShell Core executes fast (nice job M$FT, if there's one thing you do well, it's micro-optimizing!) It has nice tools for interacting with the user, like ascii art list pickers and easy input prompt generators. And, most of the strange quirks in dealing with the Windows file system are papered over if one avoids folders with locked files.

Anything you want to achieve can probably be done if you search hard enough. Recommended!

I'll agree with some of the other sentiments here that whenever my career brought me close to Windows administration I absolutely loathed the experience.

PowerShell however was actually pretty great to use, despite everything else on Windows being extremely clunky. It always felt very thoughtfully designed.

Linux is great, and I'll always use it as my daily driver for work, but using bash is absolutely horrible. But because it's always everywhere, it's something that everyone reaches for first, and so we'll probably still be dealing with bash scripts in 2100, warts and all.

Powershell was truly a product of Microsoft monopolistic confidence. To create a language that allows absolutely no syntactical carryover from any other langauge is wild. You couldn't guess or assume any command, parameter or flag. Even with Microsoft's ambition they should have realized that legions of admins and programmers had to learn and maintain scripts in both Powershell and bash for a few decades at least.

The extreme verbosity of the syntax may look good for a presentation to the committee, but dealing with it regularly collides with well-researched and understood limits of the human brain, where information of a certain size, and delays of a certain length break the state of flow and requires concentration, explicit memorization and double-takes. Even with practice one could never quickly execute the common shell incantation to turn a thought into reality, instead one would have to wrestle with syntax, even if it's just waiting for autocomplete to appear and deciding to accept the next word of a multipart command.

Let's try the start menu and search for "pow..", chose between 4 amazing options, Powershell or Powershell ISE, both in regular and x86 flavour. Either would take a while to load, breaking flow. The ISE shows a little splash screen that jumps to a second location. Another dialog shows up and informs you that you've closed the last session without saving the unnamed script files. But it opens them anyway, as you would expect. So why scold me for this? Because, you know damn well that saving the textfile is trouble: I can type or copy, and then execute any kind of evil code imaginable, but saving the file and then running it as a .ps Script triggers the ridiculous execution-policy song and dance. Probably trauma from Microsoft's bad security reputation of early Internet Explorers and Windows versions.

I tried to love it anyway but one day my script encountered filenames with square brackets. Powershell implicitly interpreted those [1] and [2] as iterators somehow (https://stackoverflow.com/questions/21008180/copy-file-with-...). Sorry but dealing with files is the one job a scripting language has, filenames are beyond the control of script authors, and the space of valid filenames on Windows should be known. This gave me some long lasting trust issues with that language.

(The Azure team aparently had enough power within Microsoft to create their own, sane and readable syntax: "az find vm", "az account show".)

> Powershell was truly a product of Microsoft monopolistic confidence. To create a language that allows absolutely no syntactical carryover from any other langauge is wild. You couldn't guess or assume any command, parameter or flag. Even with Microsoft's ambition they should have realized that legions of admins and programmers had to learn and maintain scripts in both Powershell and bash for a few decades at least.

Um... no. Powershell was inspired by shell, Perl and a bunch of other languages, you see it in its design. The other part was just a desire for consistency, since *NIX knowledge is just brute forced. Yeah, -v is generally verbose and -h is generally help, but in practice you can't rely on anything.

Could you illustrate how any other language inspired Powershell in any way, beyond the most basic concept that it is a scripting language?

In bash/unix, I feel -l often stands for list, -a for all, -f for force, -q quiet or slient, -r recursive, -d debug. A modern approach could have been for Microsoft to clean it up and make it more consistent. But no.

>> Could you illustrate how any other language inspired Powershell in any way, beyond the most basic concept that it is a scripting language?

I just posted this elsewhere in the comments, but it does answer your question:

They originally based Powershell loosely on Perl and the Korn shell. In the first edition of "Powershell in Action" by Bruce Payette there is a sidenote that states:

'PowerShell uses the "at" symbol ("@") in a few places, has $_ as a default variable, and uses "&" as the function call operator. These elements lead people to say that PowerShell looks like Perl. In fact, at one point, we were using Perl as a root language, and these elements stem from the period. Later on, the syntax was changed to align more with C#, but we kept these elements because they worked well. In Perl terminology, they contributed significantly to the "whipupitude quotient" of the language.'

It also states:

'The core PowerShell language is based on the POSIX 1003.2 grammar for the Korn shell. Originally, Perl idioms were appropriated for some of the more advanced concepts such as hash tables. However, as the project progressed, it became clear that aligning PowerShell syntax with C# was more appropriate.'

> These elements lead people to say that PowerShell looks like Perl.

> whipupitude

Historical roots and original intentions aside, the verbosity of Powershell syntax and the clumsiness of the shell place Perl and Powershell on opposite ends of the spectrum in terms of "looks" and the ability to quickly whip up something.

>> the verbosity of Powershell syntax and the clumsiness of the shell place Perl and Powershell on opposite ends of the spectrum in terms of "looks" and the ability to quickly whip up something.

I completely agree.

I used Perl for many years and loved how quickly it could be used to hack together a quick solution to a problem.

I have been using PowerShell at home intermittently for the past few years and it feels much more clunky by comparison. It is nice to have a way to do automation on Windows (I have not tried it on other platforms), but the feel is very different.

The verbosity was inspired by VAX or so I’ve heard. Dave Cutler was the big mind at the time so it made sense to me.

Edit: maybe it was VMS, not sure.

Seems so weird in retrospect that Microsoft wouldn’t have seen the value of an easily composable and programmatic way to configure anything in Windows and their other important enterprise applications like Active Directory and Exchange. The idea that connecting with Remote Desktop and clicking around with a mouse was suggested as an alternative strikes me as absurd. Especially because automating that sort of thing (at least based on my experience using autohotkey and window spy) is horrendously difficult and annoying.

> an easily composable and programmatic way to configure anything in Windows

There's an entire industry of consultants and software vendors that don't want that outcome.

> connecting with Remote Desktop and clicking around with a mouse

This generates a lot of hours.

> is horrendously difficult and annoying.

It is ironic that this is probably the main reason that alternative operating systems even exist.

Piling on, it's that industry of consultants and software vendors that keep windows in use. Microsoft protects those consultants, and those consultants protect Microsoft's market share.

Even crazier is that the “click around” mentality made its way into azure too - back in the day (a decade ago, to be fair) I had a serious suggestion from a technical support agent there that the best way to automate some setting was with Selenium…

I have never, and I mean never, been a Windows user, even though I've been using computers since 1982. During the rise of Wintel in the early 1990s, I followed the rise of Linux and 386BSD. When Win95 and NT ruled the business desktop in the late 1990s, I sought refuge in SPARCStations, Linux, and discontinued NeXT hardware. After the turn of the century, I adopted the newly-POSIX-compliant Mac OS. All this to say, avoidance of Microsoft products has been a cornerstone of my computing policy for nearly half a century (with the notable exception of Applesoft BASIC).

But PowerShell? PowerShell's nice.

You have long experience in computing and especially in the innovative currents that shifted the paradigm. Cheers!

Your first paragraph creates expectation that the second paragraph disappoints, though. Would you explain why you think PowerShell is "nice"?

It's a way of using Windows that is very tolerable to POSIX commandline diehards. The similarities are numerous and include enhanced scriptability and even small details like up-arrow command history. You could get all of that with Cygwin, but Powershell adds tight OS integration, access to COM objects (or whatever we're calling them this year) as well as the remoting of objects. It's a useful and powerful shell that reminds me of VMS DCL and csh.

> It's a useful and powerful shell that reminds me of VMS DCL and csh.

I remember watching a video on one of the various Microsoft learning sites in which Snover and another guy were interviewed about the creation of PowerShell. One of the two guys said that after they realized that UNIX-style wasn’t going to work they turned to VMS and drew a lot of inspiration from it.

Pretty sure arrow-recall predates Powershell and in fact Windows itself, it was there since DOS.

Even Tab-path completion had to be done in an incompatible way.

You posted just at the same time I asked. What's makes PowerShell better than bash?

1. Structured data passed along pipelines.

2. Automatic introspection/command completion for command parameters, even user-created commands.

You can argue about a lot of other things Powershell does, but these 2 things are things which if Bash were designed today by 100 top notch software developers, would probably be part of 95 of their designs.

Something that is under-appreciated is that if you need to write your own command-line tool with a "proper" programming language such as C/C++ or whatever, then there is a vast difference in productivity between writing for traditional shells or PowerShell.

I've never been able to make a generally useful CLI tool in under a few thousand lines of messy code. You typically have to deal with: pipeline inputs, optional parameters, parameters with values, defaults with overrides, "dry run" mode, and the various output formatting requirements, and so on. You end up with 90% fluff and 10% action.

With PowerShell, a C# module is basically 20 lines or so of overhead, and the rest is all action. It's mindblowing how productive this is! You get parameter validation, parameter name tab-complete, pipeline input, pipeline output, formatting, strong typing, globbing, etc... all for free.

While I've never used C#, I agree with you. I've moved more and more to compiled or interpreted languages versus CLI tools for maintenance and administration.

So much was so right about PowerShell. But it failed to attract a wider audience, and in their quest to woo Linux devs Microsoft has been undermining PowerShell lately. Knowing what PowerShell offers, falling back to bash CLI tools feels like two steps back.

Just some of the stuff PowerShell did right:

- PowerShell cmdlets are self-describing and rich in information. Rather than each command doing its own parsing of parameters, cmdlets describe parameters and delegates the actual parsing to the shell. The shell understands data types, parsing rules, e.g. how to parse a UUID or a date. Not only does this ensure a consistency that was never in *sh shells, but it also enables cool stuff like e.g. autocomplete, predictive input, help instructions etc. almost for free.

- "Simulation" mode (-Confirm and -WhatIf) where a cmdlet can describe the action it is about to take, and the mode of the shell may decline everything (effectively a "simulation mode") or may actually ask the user for permission (-Conform) for each action.

But, alas, PowerShell never caught on outside Windows, and now MS is leaving it to wither in their quest to not upset a wider non-Windows community.

Nushell is based on it, and it is picking up steam.


So in the end, PowerShell doesn't need to catch on.

Nushell isn’t anywhere near as powerful as PowerShell.

I think it depends on what you want to do. Nushell's never going to surpass PowerShell for Windows infrastructure automation.

But if you want a shell that makes it easy+quick to work with data in all kinds of formats, Nushell wins IMO.

PowerShell is very comfortable in interactive mode.

For scripting, I don't get it. It's not designed to be a simple text-based glue like the bourne shell is, so it feels weird in many places (quoting, escaping, even more than sh is). It's very good for glueing Windows stuff though, like .NET libraries and so on.

Huh I always found that to be the opposite. PowerShell is clearly designed to be a programming language not an interactive environment.

E.g. 'wget' exists but run it on its own and it doesn't save the file to disk or print it out, it prints an object as a table, which is about the most useless output possible. I know why this happens but that doesn't make it helpful.

Reading about the dysfunction inside Microsoft makes it clear why it ended up this way though!

I don't want an object oriented language to glue stuff, I want a glue language.

Want the result of wget in memory instead of print or disk? Write it to memory:

    page_contents="$(wget -O- some_page)"

It doesn't try to apply some default structure, so I don't need to rely on MS doing a fancy special wget for me that calls thousands of lines Invoke-WebRequest in the background.

Does the ISE still take forever to spin up?

I think everyone just uses VSCode now

The ISE is deprecated, and MS guidance is that it should be uninstalled. Defender endpoint management flags it as a mild security risk.

LOL what a fall from grace. The ISE was/is terrible!

I once had 2 microsoft engineers call me for help with qmail because I was active on the qmail mailing list. They couldn't wrap their heads around how svc and daemontools worked.. the good old days! I never asked why 2 microsoft engineers were working with qmail. I think I was 20 at the time and I was just happy to be on the phone with people from Microsoft even though I was very much a Linux guy.

I love corecursive! Keep up the good work @adam!!

The Monad Manifesto mentioned in the podcast:


I used to be a hardcore Windows dev but never figured out powershell. I actually ended up writing scripts in C# and had a utility to load and run it.

That's what they should have done. Have a C# interpreter with maybe a few extensions for shell stuff. Powershell is not a good .NET language and not a good shell. It's just a weird beast.

A while ago I worked on a project to do pretty complex configuration on Windows machines. Everybody thought Powershell would be perfect for this. It turned into a complete nightmare with tons of oddities to work around. I myself barely can make sense of the code and I bet nobody else can.

Next time I would do either Python or write the whole thing in C#.

Good news. You can write C# that powershell will compile on the fly. It's so ingrained in Microsoft applications that even MSSQL Server will do it as well, if you want to go down that route.


Executing C# in Powershell: https://blog.adamfurmanek.pl/2016/03/19/executing-c-code-usi...

Executing C# in SQL Server: https://learn.microsoft.com/en-us/sql/language-extensions/ho...

An anecdote: about 7 years ago I made an postal code lookup function for SQL server, that would parse a csv from the danish postal services, that was retrieved from a HTTP GET in T-SQL, then parsed with C# to get the city from a postal code. It was a project i did for fun at school.

I think PowerShell is a bit scary, for example I could never get curl to work in it, say a simple POST command: curl -X "POST" google.com should return Error 411 (Length required) from google (as it does in CMD.EXE)

When I try it in PowerShell I get: Invoke-WebRequest : A parameter cannot be found that matches parameter name 'X'. and some more error messages

even curl -X "GET" doesn't work :-(

That is because `curl` is an alias for the builtin Invoke-WebRequest and not the actual curl program.


It was at one point, but they took it out because it was stupid.

Well that's just plain stupid

This is a great story of finding a way to be productive inside a giant, impersonal machine like Microsoft.

That said, it did nothing to convince me to invest more mental energy in PowerShell. Every time I use it, I have the same “meh” reaction: The learning curve is too steep and the syntax is too ugly. It doesn’t ever “stick” with me, so I end up starting from zero every time I encounter it again.

I think the fundamental problem is that PWSH inhabits a dark valley between quick-and-dirty scripting and I’m-serious-about-this programming. It really needed to pick one side or the other to win people over, but never did.

I found the most interesting part about this article how it kind of makes a direct line from UNIX’s place as a place for programmer system admins versus professional services-driven servers.

These people at Microsoft knew that they’d wipe the floor with the professional services folks by getting that professional services cost out of the picture by providing the small UNIX-like toolbox to do sysadmin work via automations.

Of course, PowerShell being API-based instead of file-based was what came out of that.

It’s interesting because what has survived has essentially been Windows and UNIX (via Linux being able to drop all the proprietary baggage of UNIX solutions). Everything else that was built to sell professional services is dead.

Big fan of PowerShell. Such a shame that being in Microsoft, you aren't allowed to do great work. That is why hackers shouldn't join large companies. You can create much more value working for yourself or joining a small startup.

Besides the whole interesting story background, yet another confirmation of the anti-.NET bias by WinDev during the Longhorn efforts.

Instead of uniting and having everyone collaborating into a common like Google with Android making it happen no matter what, or how Bell Labs tried with Inferno / Limbo, the active fight against .NET, and anything related.

To what ended up being the WinRT failure.

Ironically, WinDev is now shipping JavaScript and Webview2 all over the place on Windows 11.

Would have loved to hear why he made the move to Google considering that he became a Technical Fellow and very popular in the community

PowerShell, is still the best way to scale your workload, administering a Windows server environment on premise. For Azure, there were features that were present in the Graph API that were not in PowerShell.

I haven't checked back in a while, but I think most new features in PowerShell are just pointing back to the Graph API.

PowerShell helped me a lot in my earlier career, bash always felt like banging rocks together in comparison.

It says a lot about the uphill battle that he faced when the first two sentences Jeffrey says in the podcast are "By the way, is it okay to swear?" and "You know, I had executives say, ‘Jeffrey, exactly which part of fucking Windows is confusing you, Jeffrey?’".

Favorite line:

"I’ve never seen anybody use a GUI in a clever way. Ever. There’s no cleverness to it. No, like, Oh my God, you should see the way Adam clicked that mouse. Oh my God. Guys, guys, guys, guys, come on, check it out. Adam’s going to click the button. Oh my God. That’s amazing. It just doesn’t happen."

To be fair, a GUI can be used in a very clever and skillful manner. It's called keyboard shortcuts (and, to a lesser extent, mouse gestures). You can't deny an Excel world champion uses its GUI in a highly impressive way. And features like multiple carets editing (as popularized by Sublime Text) makes it possible to perform some remarkable editing feats. :)

Thanks for this. Just seeing the word "PowerShell" gets me excited every time... been using it for hours a day for years and it's so much fun. It's how I first learned to code, professionally. Kudos and Cheers!

I am not a fan of PowerShell, but I am a fan of Jeffrey--he toiled and talked sense at a time way before Azure was a thing, but everything since he shipped has proven he was right.

I wonder how many engineers use AWS's Powershell cmdlets?

They are incredibly well built and feel first class/more polished than a lot of AWS tools.

Honestly I love Powershell and run it on Linux or OS X. Being able to access fields instead of having to play with `cut` to get the data I want is priceless. Just feels cleaner and more maintainable.

Why wouldn’t they just replicate bash or some other UNIX shell, along with the basic UNIX tools like cp and find with matching APIs? Huge mistake there imo, even if they did add a few bells and whistles with powershell

I love this podcast!

PowerShell is MIT licensed, cross-platform Windows, Linux, macOS compatible, and you can download it in various installers and packages here: https://github.com/PowerShell/PowerShell/releases

for anyone who wants to try the newer version on Windows, get either Windows Terminal (from Microsoft Store or Github releases: https://learn.microsoft.com/en-us/windows/terminal/install) or Visual Studio Code. The classic Windows' command prompt console host engine just can't do Unicode and fonts and colours and Unix shell escape sequences.

After that, find something which will immediately trigger you to froth at the mouth, hurry onto some Microsoft forum and post about how Microsoft is the devil. Here's some popular choices, many of them valid complaints: ('curl' and 'wget' on Windows override the real programs with M$ imposters). (gci doesn't support the parameters of either dir or ls). (aliases work differently to Unix shells). (almost everything works differently to Bash). (gci -recurse is frustratingly slow). (it doesn't have a CLI text editor like nano). (you don't understand that GNU and Unix utilities aren't "Bash"). (PowerShell remoting with enter-pssession and invoke-command aren't SSH). (there isn't any sudo because Windows isn't Linux). (Execution policies are annoying). (it doesn't use UTF8 everywhere always). (backslash, the one true Unix escape character isn't PowerShell's escape character). (Line endings aren't Unix line endings). (having to use sigils to disambiguate between shell and code is worse than Python for coding and worse than Bash/cmd for shelling). (You want > to be both numeric comparison and/or Unix shell IO redirect and it's not). (you hate Verb-Noun and the one true way is Noun-Verb). (byte streams don't pipeline well or quickly). (It's verbose which you hate, but the elastic syntax one-liners are unreadable which you hate, it should have exactly the right amount of verbosity which coincidentally is exactly the amount you are comfortable with).

Moving on from there, avoid falling for the tempting usermode filesystem equivalent, which is abandoned and only exists for backwards compatibility making everything slower. Avoid falling for the declarative host config system Desired State Configuration (DSC) which is semi-abandoned and only hangs around for backwards compatibility. Control your enthusiasm about .NET/C# LINQ in a shell, because nope. Prepare yourself for the weirdness of a programming language which has shell style dynamic scoping instead of lexical scoping, shell style output handling where all output goes to the pipeline, pipeline obsessed array unrolling which spills the contents of containers all over the floor if you aren't paying attention, having to learn that there's more to output than just stdout and stderr and that the host and pipeline are different outputs, and that there's a lot of non-powershelly .NET and Windows stuff poking through everywhere. Prepare your armoured-toe boots for a large number of footguns and bugs in what is an intricate and complex shell/scripting language mashup.

Moving on from there, it's a REPL:

    $x = 5
    $x + 3
Numeric literals in hex and binary:

Strings in single quotes are literal:

    'foo $bar'
Strings in double quotes are not literal:

    $bar = 'hello'
    "foo $bar $( 4 + 3 )"
It's a shell:

    ping google.com
It's introspective:

    gcm ping    # get-command details of ping
    gcm p*      # commands starting with pi
    help gcm
Function calls don't use () or "return" because shell-style usage and behaviour, variable names and function calls aren't case sensitive:

    PS C:\> function test($Left, $Right) { $left + $right }
    PS C:\> test 4 6

    PS C:\> test -Left 4 -Right 6  # named parameters
    PS C:\> test -L<ctrl+space>    # autocomplete
Reach for .NET libraries:

    PS C:\> [System.Ma<ctrl+space>  # autocomplete to explore and find System.Math
    PS C:\> [System.Math]::<ctrl+space>  # autocomplete to find e.g. [System.Math]::Pow(4, 5)
Basic data types:

    $array = 1,2,3
    $array | foreach { $_ }

    $hash = @{KeyA = 4; KeyB = "b"}
    $hash.keyC = 5
    $hash['keyD'] = get-childitem

    $x = 'KeyA'
    $hash.$x   # oooh
on Windows:

    gci | ogv    # out-gridview
Text filter ("grep ish"):

    gc words.txt | sls '[iou]'    # get-content and Select-String

    ls | select Las<tab>  # tab complete will pickup the available properties
                          # on the objects coming through the pipeline, where possible

    ls | select LastWriteTime, FullName    # two properties, kept separate, no text parsing

    ls | % {$_.LastAccessTime.DayOfWeek}   # the access time is a .NET System.DateTime,
                                           # not a timestamp or text string.

    ipcsv data.csv | select col1, col3     # import-csv, select-object

    $hash = @{KeyA = 1; KeyB = "foo"}
    [pscustomobject] $hash                 # casting
(Objects are used as containers for multiple properties and keeping them separate; it's not a full "object oriented programming with inheritance and interfaces" kind of shell/language, although it has some nods to that).

I met Snover at a DevOps Days forever ago. We were talking about PowerShell, and I didn't know he was at our table. Super nice dude.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact