The Superpower
Bash is a text-processing shell. Every command outputs a stream of characters. When you run ps aux, you get a formatted table of text. To extract the memory column, you must know it is the fourth field, use awk '{print $4}', and hope the column alignment never changes. This works, but it is fragile — it breaks if the output format changes between OS versions or locales.
PowerShell is fundamentally different. It is an object-based shell built on the .NET runtime. When you run Get-Process, you do not get text — you get a collection of .NET Process objects. Each object has named properties: .Name, .Id, .WorkingSet, .CPU, .StartTime. You interact with those properties by name, not by column position. The pipeline passes objects between commands, not strings.
The Practical Difference
Consider finding the five processes using the most memory. In Bash, that means piping ps aux through sort and head — but first you have to know that memory sits in the fourth column, and hope the column alignment never shifts between OS versions or locales. In PowerShell, the equivalent — sorting Get-Process by WorkingSet and selecting the top five — reads like English, because you're asking for a property by name rather than counting columns. It will not break if Microsoft changes the output format, because nothing is being parsed as text.
Verb-Noun Syntax
PowerShell enforces a consistent Verb-Noun naming convention for all commands (called cmdlets):
| Verb | Meaning | Example |
|---|---|---|
Get |
Retrieve information | Get-Service, Get-Process, Get-Item |
Set |
Modify a value | Set-ItemProperty, Set-Service |
New |
Create something | New-Item, New-LocalUser |
Remove |
Delete something | Remove-Item, Remove-LocalUser |
Start / Stop |
Control lifecycle | Start-Service, Stop-Process |
Invoke |
Run something | Invoke-Command, Invoke-WebRequest |
This consistency means you can often guess a command. Need to restart a service? Try Restart-Service. Need to get firewall rules? Try Get-NetFirewallRule. This discoverability is a major advantage over Bash, where every tool has its own flag conventions.
Filtering and the Pipeline
The Where-Object cmdlet filters a collection based on a condition, using the $_ variable to refer to the current object in the pipeline — for example, filtering Get-Service down to services whose Status equals Stopped. Comparisons read naturally because PowerShell understands MB, GB, and TB as numeric multipliers directly in an expression, so filtering processes over a memory threshold or files modified within the last week is a single readable condition rather than a fragile text pattern.
Remoting: PowerShell Over the Network
PowerShell Remoting (PSRemoting) is the Windows equivalent of SSH for automation. It uses the WinRM (Windows Remote Management) protocol, which runs over HTTP (port 5985) or HTTPS (port 5986). The Invoke-Command cmdlet runs a script block against one or more remote computers and returns the results as objects, while Enter-PSSession opens an interactive remote session comparable to an SSH login.
A common interview question is: "How do you run commands on 50 Windows servers simultaneously?" The answer is Invoke-Command with the -ComputerName parameter accepting an array of hostnames, combined with -ThrottleLimit to control parallelism. For larger scale, the answer is Ansible with the winrm connection plugin, or AWS Systems Manager (SSM) for cloud instances. Knowing both the native PowerShell answer and the cross-platform tooling answer demonstrates real operational experience.