PowerShell: The object-oriented shell you didn't know you needed

https://chriswarrick.com/blog/2024/04/29/powershell-the-object-oriented-shell-you-didnt-know-you-needed/

49 points by todsacerdoti on 2024-04-29 | 80 comments

Automated Summary

PowerShell is an interactive shell and scripting language from Microsoft that is object-oriented, which differentiates it from standard Unix shells. There are two versions of PowerShell: Windows PowerShell (5.1) and PowerShell (7.x), formerly known as PowerShell Core. The article covers PowerShell's object-oriented approach, comparing it to Unix shells and demonstrating the difference with a directory listing example, showing how PowerShell returns an array of objects. The article also briefly introduces PowerShell's filesystem operations and covers more complex scenarios such as Grouping Files by Directory, Duplicate File Detection, and generating a Software Bill of Materials using PowerShell.

Comments

OkayPhysicist on 2024-04-29

I like PowerShell a lot more than bash, but it's got so much weird jank. String escaping gets pathological when passing arguments to cmd, or bash, or worse, both, which happens more than you'd think (looking at you, Azure CLI), and there's no good way to pipe raw bytes around (like, say, when you want to checkout a binary file from git). There's no real need to differentiate between HashTables and Objects, but it does, and it bites you at random times. IMO, they would have been better off dropping the < and > piping operators, leaving them as | Out-File and Get-Content | and then used the arrows for less than and greater than, and used == as equal to, instead of the -lt -gt -eq nonsense.

jborean93 on 2024-04-29

> and there's no good way to pipe raw bytes around (like, say, when you want to checkout a binary file from git).

Since pwsh 7.4 it can natively pipe the raw bytes between two external binaries and also when redirecting to a file. Sucks it took until then to get it but it's now there.

wvenable on 2024-04-29

Yeah this my main complaint with Powershell -- Microsoft had one opportunity to build a new shell for the ages and decided to use Bash for syntax inspiration. It could have been so much better and now we're stuck with it forever.

fr4nkr on 2024-04-30

Powershell feels a lot like Microsoft wanted to appeal to *nix users, especially system administrators, without really understanding them, presumably because D̶a̶v̶e̶ ̶C̶u̶t̶l̶e̶r̶ ̶s̶h̶o̶t̶ ̶t̶h̶e̶m̶ ̶o̶n̶ ̶s̶i̶g̶h̶t̶ Microsoft's way of doing things was and is considerably different. As a result, it hadn't really occurred to them that much of bash's weirdness and flakiness is historical, not simply because *nix users prefer it that way.

The end result was still a much better language than bash, of course, but that's a very low bar.

spiralx on 2024-05-01

It was actually inspired by Perl as much as Bash if you read one of the asides in the O'Reilly book written by one of PS's developers lol.

tester457 on 2024-04-29

I rather nushell for this purpose, it's more fun to write and easier to read.

https://www.nushell.sh/

kej on 2024-04-29

This is what I've moved to lately. I like the idea of structured data but PowerShell just feels like a shell designed by people who don't really want to use a shell.

notesinthefield on 2024-04-29

Id posit thats exactly what they want. I started my career using 100% Linux-based tooling and slowly moved into Windows land - I have not ever liked Bash, only tolerate Fish, love Powershell. Ironically I think its biggest limitations are Windows’ fault. They want to latch on to the old point and click guard.

albertopv on 2024-05-01

No deb package though

canadianfella on 2024-04-29

I think you mean “prefer” and not “rather”.

bestouff on 2024-04-30

.. or (s)he forgot the word "use". Maybe we'll never know.

tester457 on 2024-04-30

You're right, I forgot "use". And I would change "I" to "I'd" if I could still edit.

nrr on 2024-04-29

I like the idea of PowerShell, but my constant lamentation is that it doesn't go deep enough to be considered a true shell. Many of the things that I lean specifically on bash or ksh or cmd.exe or yori.exe for ultimately lead to breaking into C#. PowerShell makes them painful.

In my mind, it competes more with Python than Bourne shell: it's a scripting language that only tenuously gives you a DSL for interacting with processes and the streams between them.

felsokning on 2024-04-29

PowerShell is great -- but there are some things you simply cannot do with it. For example, try to escape '$', which can be included in urls but can't be used in Invoke-RestMethod.

Bash via WSL saves the day, in this regard (e.g.: $results = wsl ./myAwesomeBashScript.sh).

While PowerShell is great as object-oriented scripting, it still can't handle simple tasks that can be done in the likes of bash, zsh, etc.

jborean93 on 2024-04-29

To escape $ you either need to use a single quoted string so the $ is treated literally or in a double quoted string use a backtick before the $ to escape it

    Write-Host 'Foo$Bar'
    Write-Host "Foo`$Bar"

RajT88 on 2024-04-29

A lot of people's complaints in this thread are because they just haven't figured out the powershell way of doing that thing.

Granted - the Powershell way of doing some things is stupidly obtuse sometimes.

felsokning on 2024-04-29

In the issue I ran into, the '$' comes back from Azure in the nextLink[1] value. As soon as you try to process the string, the reserved token '$' breaks any processing - precisely because it wasn't escaped before being stored.

Perhaps, it's easy enough to do some .NET manipulation, just to get PowerShell to be able to handle the string for the next Invoke-RestMethod -- but its far easier to just curl those urls, instead.

[1] - https://learn.microsoft.com/en-us/rest/api/keyvault/keyvault...

4rt on 2024-04-29

I'm a huge fan of powershell, especially for build scripts and other things that get complicated sometimes. Parsing XML and JSON, calling web APIs and dealing with their responses are all about as easy as they can be.

The article covers all the main (minor) bugbears.

mhx1138 on 2024-04-30

Microsoft is driving fragmentation with Powershell. It doesn’t really matter if it’s better than bash or not. Bash is good enough for most use cases. Yet e.g. so many of their examples for using cloud apis are in powershell, which instantly alienates everyone who doesn’t want to commit learning a redundant tool.

It expresses an arrogance and disregard for their users and makes a group of people just walk away from it. That’s totally unnecessary.

riperoni on 2024-05-02

Either i overread it or one major quirk is totally not touched on: PowerShell is case-insensitive in as many places as possible, except file paths or the likes.

You can actually call .NET methods with completely nuts casing: "asdfg".tOupPer() works.

Also variable names with only different cases resolve the same, i.e. $var is the same variable as $Var.

String comparison with PowerShell operators is case-insensitive and it has special operators to match case sensitivity. RegEx operators behave the same way. Using the .NET methods however conserves case-sensitivity.

I enjoy using PowerShell a lot. In many of places for scripting processes (Windows server adminisitration) it has an easier entry point than Python. And handling complex objects is kind of trivial. The Windows PowerShell really shows its age by now though and I hope the new PowerShell will be included by default, too.

chasil on 2024-04-29

Powershell's fatal flaw is size.

The Debian dash POSIX shell can compile under 100k on i386.

This is a space where Powershell can never be.

davidmurdoch on 2024-04-29

Do you actually care about this?

thefaux on 2024-04-29

Not OP, but I do. In principle it shouldn't really matter what the size of the binary is, but a large binary relative to peers in the program's category usually reflects complexity and bloat. Powershell feels sluggish and unresponsive to me relative to fish, bash or zsh (the three shells I've used most). I was so put off by the feel of powershell five or so years ago that I haven't used it since then. For that reason though, I will concede it's possible it's better now but I'd be pretty surprised given Microsoft's track record.

faeriechangling on 2024-04-29

It’s still a lousy interactive shell, although it’s a fine sysadmin oriented scripting language and better than bash/zsh/fish for such purposes.

You’d only ever use it to work with Microsoft stuff though, and older Microsoft stuff at that.

chasil on 2024-04-30

I care about dash because when I write for it, I write for them all.

The speed and economy of size are a side effect.

davidmurdoch on 2024-04-30

I don't understand. How does the size of an application change how you write code?

bayesianbot on 2024-04-29

And slowness, which might be related to the size. I was using PowerShell for months and loved it, until one day I needed to start fish shell and it felt amazing, the experience was just so lag-free compared to PowerShell. I didn't notice it while using PowerShell but after that I could never change back. Also shell startup speed felt quite meaningless before but after getting used to few second startup delay with PowerShell, it was so nice to just open terminal and start typing instead.

robomartin on 2024-04-29

That may have been relevant in the era of the IBM PC with 1MB of memory and 10MB hard drives. Today and going forward? Almost irrelevant. Even embedded systems have massive resources these days.

This isn't to say I am not critical of some aspects of PowerShell. I am simply saying that being critical about compiled software size is something that left the building a long time ago as a valid concern. I am very much into efficiency and performance in software. As much as I hate it, these are not metrics that make the difference between winning and losing for most software applications today.

skissane on 2024-05-01

> Powershell's fatal flaw is size.

I wonder how big PowerShell would be if it was reimplemented in WinRT instead of .NET

whalesalad on 2024-04-29

Windows is already bloated to high hell. Being concerned about powershell's size feels like rearranging deck chairs on the titanic.

jdiff on 2024-04-29

PowerShell exists on other platforms

whalesalad on 2024-04-29

why in god's heavenly image would you use powershell anywhere but windows

unclad5968 on 2024-04-29

I use it on other platforms so I can use the same scripts no matter where I'm developing. Also github ci

pjmlp on 2024-04-30

For the same reason one would use Python, Ruby, Perl on Windows, outside UNIX.

Portable scripts.

dekhn on 2024-04-29

powershell is a 440k executable on my machine. functionally, it's much more capable than dash. I don't think powershell is even remotely interested in competing in whatever space you are in.

jborean93 on 2024-04-29

PowerShell also needs all the other dll's located next to the executable so it's way more than 440k. Granted I agree that this isn't a space they really care about and the problem is more due to the dependency on .NET itself.

dekhn on 2024-04-30

Well, I assumed the 100K dash shell also was dynamically linked (presumably to libc and the linker loader). But yes, you're right, I wasn't including all the DLLs and all the various modules/scripts you can invoke. from my inspection, it looks like DLLs that are probably already loaded just by booting a system.

jborean93 on 2024-04-30

It's more for pwsh (7+) as that bundles it's own copy of the .NET runtime. The powershell.exe (5.1) is the version included in Windows and uses a shared copy of the .NET Framework included in the GAC. When looking at the size of modern PowerShell (7+) you do need to take into consideration the size of the .NET runtime which is quite sizeable. Personally it's not a problem for me and while I don't agree it's a fatal flaw it's certainly a downside compared to other shells.

pjmlp on 2024-04-30

I doubt anyone is using PowerShell on Arduinos.

faeriechangling on 2024-04-29

Ever since Microsoft decided with Microsoft Graph that “everything is a string” and “Everything is a REST API call” PowerShell has honestly seemed dumber and dumber to me. It’s great at manipulating Win32 stuff and pretty much perfect for that task sure but it’s in a weird place now since Bash and friends were always better for simple string manipulation tasks.

Backticks for line continuations was also a satanic decision, even knowing of the myriad alternatives to them in PoSH.

nrr on 2024-04-29

I'm still holding out for a Tcl port to the CLR (StrongTcl? IronTcl? Tcl#?) for exactly this reason.

6c on 2024-04-30

There is Eagle: https://eagle.to (never used it, just aware of its existence)

nrr on 2024-04-30

Oh, this looks like a real gem. Thank you for making my day today.

pjmlp on 2024-04-30

As someone that was in a startup built on top of Tcl during the dotcom wave, I doubt Tcl is coming back as it was back in 2000.

buzzin__ on 2024-04-29

Why is world not in the hashset? Even gptchat4 doesn't know and thinks it could be because of out-null, and i should try without it. Anyone?

TedHerman on 2024-04-30

I mainly use Python to work with typical shell functions and external programs. I contend that Python and other similar languages are superior to PowerShell.

swozey on 2024-04-29

I have tried many, many times to work with posh. I was even a very senior windows engineer at some of the largest webhosts when it came out and used it heavily because the fantastic Windows Server operating system comes with literally no tools any bsd/nix engineer expects, you know, like rdp brute force detection blockers to actually manage servers, or .. my gosh, IIS URL REWRITES. BFD isn't "baked in" to linux but nobody is hiding their secret sauce so every company has to roll their own vs pulling a package from apt for bfd, etc. Here's your $expensive$ Windows Service license, now spend $20k in dev hours for someone to write a powershell script that monitors eventvwr for failed rdp event errors, extract the ingress ip into a db and block across the board.

I remember being fascinated by its history because the main guy wrote it, Jeffrey Snover, I'm going to butcher this, but IIRC he was some sort of big posix/shell/bash/perl/something-very-shell-important and wanted to take the best of whatever systems he was familiar/contributed/wrote and improve them and make that powershell.

Anyway, yeah I absolutely despise using it. It's syntax is atrocious. It's key words aren't memorable in the least. I know some people absolutely love it, even people who aren't using it in Windows. But it's never clicked for me.

I found this thread interesting. I guess Snover left MS after 23 years there in 2022, and he was demoted at some point after creating powershell. I don't care enough about it to dig into why but if anyone is interested- https://news.ycombinator.com/item?id=31302174

I did windows engineering at the biggest webhosts you know, RAX, HG, etc. Being a Windows Eng in webhosting is incredibly uncommon. Prior to that and post I'm back as a bsd/linux engineer (distsys/sre now) and the Windows Server ecosystem is absolutely abysmal if you aren't in it for Exchange, MSSQL, or whatever random Windows-Only app your company uses. I supported that trash from server 2000 - 2012 r2.

Never again.

geenat on 2024-04-29

Honestly bash would be fine if the control structure syntax was a bit more sane.

(... and set -euo pipefail was default). Bash scripts can be tiny for what they do, and the ssh integration is unmatched.

xonsh is nice but it's been unstable for me lately.

nushell is nice but not sure if it's worth switching the default for.

TheRoque on 2024-04-29

Cool, but it still can't properly autocomplete anything so I'll try to get that working first

bogwog on 2024-04-29

Unfortunately, all the PhDs at Microsoft were moved to AI projects.

oscillatingpie on 2024-04-29

It ships with PSReadline now which gives it bash like autocomplete.

TheRoque on 2024-04-29

Is it something to install separately ? Or I need to upgrade something ? I never got it to auto complete anything to be honest

jborean93 on 2024-04-29

It's been shipped with PowerShell since v5.1 (Windows 10/Server 2016). There have been numerous updates to PSReadLine since then to add more features but tab completion has worked for years and is IMO one of the biggest selling points.

TheRoque on 2024-04-30

Weird. Coming from the fish shell, I can't really get anything completed with PowerShell. Mostly, I want it to work with my git commands (detect my branches for example).

jborean93 on 2024-04-30

Ah if you want auto completion for native commands they need to be registered first. PSReadLine provides autocompletion support but it only works by default with things builtin to PowerShell itself. For `git` there is a fairly popular module called posh-git [1] that provides auto completion support for some of the well known commands. Git for Windows also calls it out [2]. You can also provide your own custom auto complete calls with Register-ArgumentCompleter [3]. Hope this helps!

[1] https://github.com/dahlbyk/posh-git [2] https://git-scm.com/book/ms/v2/Appendix-A%3A-Git-in-Other-En... [3] https://learn.microsoft.com/en-us/powershell/module/microsof...

TheRoque on 2024-04-30

Thanks for the help ! I will definitely set this up. But if I have to install some extension for every single command I use, it really makes the experience tedious and sub-par compared to what I'd get on Linux..

supernovae on 2024-04-30

only because your linux distro is doing it for you not because bash has git completion built in.

tyleo on 2024-04-29

TBH I’ve despised the object oriented parts of PowerShell… and it’s been my primary shell for a decade. I just mainly use it with text.

Aloha on 2024-04-29

Sorta agree - I'm mostly doing string handling and parsing on windows boxes - so I often just want it to compare on a string or whatever.

But sometimes the "everything is an object" is useful in ways that would be really hard to do on unix like systems.

mattbee on 2024-04-29

Yeah it's pretty good! I wrote a few hundred line build script for a Windows project last month. I knew no powershell last month, and now it makes more sense to me than bash which I've used badly for 25 years.

Actually on Linux I tend to use Ruby for any non-trivial scripting, and it feels much closer to that. So it's probably no coincidence that I've got on with it.

pdntspa on 2024-04-29

Powershell's syntax is so fucking weird and verbose. I guess if you live in Microsoft land all day and write code in C# it's fine, but I would really like it if we all could collectively agree on one set of syntax rules. I don't even care what they are. But as a polyglot I am so sick of having to learn yet another syntax. cmd.exe does everything I need to and batch is actually kind of flexible.

Also, I don't know what it is with shell programmers (and I've worked for one) but bash syntax is similarly insane. I am so glad I've never had to write an init.d service because 20 years into my linux career I still can't read that shit. Like I can launch and fork a process in like 10 lines of C, but it's five pages of gobbledygook shell script?

gwervc on 2024-04-29

> I guess if you live in Microsoft land all day and write code in C# it's fine

I write C# daily but I'm not fine with powershell syntax. It seems harder than it should be.

Aloha on 2024-04-30

I always joke and PowerShell must have been created by someone who types 300 WPM ;-)

supportengineer on 2024-04-29

I always thought Lisp or Smalltalk might be good for a shell.

faeriechangling on 2024-04-29

It’s weird on account of dealing with a legacy of Microsoftisms, including from cmd.exe which is why it has to use -gt as a comparison operator and not >.

Batch is not nearly as flexible as PoSH although the interpreter still boots faster so I use cmd.exe all the time.

mr_toad on 2024-04-29

> bash syntax is similarly insane

At least it’s terse, which is good when you’re typing commands on the fly on the command line. PowerShell on the other hand is so unwieldy on the command line. Even the pervasive use of case slows down typing.

MatejKafka on 2024-04-30

With aliases, powershell can be quite terse as well, and since it's case-insensitive, you can just type everything in lowercase.

MatejKafka on 2024-04-30

E.g. instead of the script presented in the article:

    (Get-ChildItem -Filter '*.txt' | ForEach-Object { $_.Length } | Measure-Object -Sum).Sum
You can do

     ls *.txt | measure -Sum Length | % Sum

RajT88 on 2024-04-30

> Powershell's syntax is so fucking weird and verbose.

You're not wrong. I think it's that way because of trying to increase readability. Best practice for Powershell cmdlet development is verb-noun.

Of course they throw that out the window with aliases.

Examples:

wget and curl both are aliases for invoke-webrequest

iex is an alias for "invoke-expression" - which lets you execute a string as powershell code in your same session (note: I originally wrote scriptblock, which was incorrect - otherwise something I wrote this week wouldn't work at all, due to change of scope). This ability gets me out of a lot of weird jams.

The other thing too which makes it so weird is that it is built on top of .Net. The overarching principle of Powershell is that it's your Windows swiss army knife. You can access .Net classes by loading the assemblies. I have on occasion built a small WinForms app in powershell. You can create and invoke COM objects (new-object cmdlet).

> But as a polyglot I am so sick of having to learn yet another syntax.

Personally, I try to avoid "language specific sugar" when I am writing sample scripts for people (I am in a customer facing role). But goddamn I love the shorthand way you can do a for loop in Powershell using the range operator:

1..100 | % {Write-Host $_}

> cmd.exe does everything I need to and batch is actually kind of flexible.

OK, so you haven't really gotten to know Powershell very well if you're saying things like this. lol

Scripting in batch files is like living in the dark ages. They are "kind of flexible" whereas Powershell is "very flexible, most of the time".

And that "most of the time" caveat is no longer there if you are on the latest powershell (which doesn't work with the ISE as ISE is 5.x only, and the way of the future is the universal PWSH). My biggest gripe was fixed I think in Powershell 7, which was manipulating files with grave marks in the name.

I build a lot of stuff in Powershell, as you can probably tell. Given all the interop stuff it has, once you know how to use it all, the point where it makes sense to build it in C# is farther down the line than you might think.

doubloon on 2024-04-29

thats what Copilot is for. You just go "please tell me how to work this grep | awk command in powershell"

RajT88 on 2024-04-30

I've had some great success with C# and Powershell and Copilot/ChatGPT.

It writes impeccable code - but doesn't always get the question right. I've found most of the time, even when it gets the question wrong, it turns you onto the right path forward. Definitely has saved me a lot of time researching things.

pdpi on 2024-04-29

And, presumably, I'd prompt copilot to write those things for me... from within powershell? Using what command?

Generative AI can do a lot of fun things, but we're talking about a but it does not belong anywhere near an interactive shell.

supernovae on 2024-04-30

on windows copilot is built into the task bar with a popout window on right side bar showing output that can work with clipboard. You can talk to it, copy in an image or screenshot and ask for details too. if you prompt for PowerShell it gives you a code block with a copy button. (oh and also reference links to learn more... which is much nice)

pdntspa on 2024-04-29

I kind of see these AI tools like a superhero's toolbelt -- great, when it's on you. But one doesn't always have the luxury of internet access. It is best not to overrely on AI, or any cloud service for that matter.

doubloon on 2024-04-30

if you dont have internet service and you are on a windows box, you are SOL in the first place.

pdntspa on 2024-04-30

This is an absolutely awful attitude. All you need to do to witness lack of internet yourself is drive a couple hours' north of San Francisco. Now imagine that a huge chunk of the world is far worse off than this.

doubloon on 2024-05-04

if i was in an environment without internet, i would be using open source software.

dpkirchner on 2024-04-29

Is there a cmdlet that will do this automatically?

robomartin on 2024-04-29

> Powershell's syntax is so fucking weird and verbose.

Yeah. At a certain point it is almost impossible to internalize that complexity.

As someone suggested...in the era of AI, this might not matter at all.

pdntspa on 2024-04-29

AI is many things, but deterministic with natural language it is not.

koko-blat on 2024-04-29

[flagged]