For a long time, the unspoken rule in Linux circles has been that PowerShell is a Windows thing, and Bash is the real deal. Even I maintained this position at first, because early iterations of PowerShell felt clunky, were Windows-only, and weren't being widely used by choice. That version of PowerShell hasn't existed in years, but the Linux community still has a reputation for dismissing it despite its progress.
PowerShell has been open-source and cross-platform for a decade now. It's no longer a Windows-only administration tool, as it has native builds for both Linux and macOS as well. I used to think of it as a terminal I needed to open whenever a script was written for PowerShell, but I'd close it afterward without much consideration. Once I sat down with PowerShell for a real project, I realized that it was no longer something I should be writing off.
PowerShell's object pipeline changes scripting
Bash is limited by treating everything as a string
It took me longer than I'd like to admit to wrap my head around what makes PowerShell so unlike Bash. It finally clicked when I realized one fundamental difference between the two: PowerShell pipes objects, and Bash pipes strings. In Bash, every command outputs text, and then you figure out how to manipulate that text into something useful. This usually involves a lot of piping to grep, sed, and awk to parse raw output, even for relatively simple tasks. Those tools are powerful, and I still use them constantly, but I have to concede that PowerShell makes a lot of things simpler.
Here's a quick example that illustrates my point. This PowerShell pipeline filters processes by CPU usage and selects their name. Anything above 10% CPU usage will appear as output:
Get-Process | Where-Object CPU -gt 10 | Select-Object Name
Now, here's how you'd write the equivalent in Bash:
ps -eo comm,pcpu | awk '$2 > 10 {print $1}'
The difference there is immediately noticeable in the readability alone. But it runs even deeper than that, because PowerShell is piping objects, rather than just text, to each subsequent command. Bash is using awk to isolate the column we want and to keep processes using more than 10% CPU. This is only a basic example, but more complex Bash scripts and pipelines use awk and sed liberally, and they'll break if a command hands them output in a format that deviates at all from what they expect.
For short one-liners like the example above, the difference isn't so important in day-to-day tasks. The true payoff is in longer scripts that have real logic, like conditional branching, error handling, and data transformation. That's where the object model excels. Not only are most of my PowerShell scripts significantly shorter than their Bash equivalents, but they're also much easier to revisit a few months later. With Bash scripts I haven't touched in a while, it takes me at least a few minutes to study the pipeline and remember how it's manipulating the data.
Bash still wins on portability
For my own machines, that advantage disappears
Bash is downright ubiquitous, and it's not going anywhere. You'll find it on every Linux system you SSH into, and every Docker container drops you into that familiar Bash prompt. Plus, scripts written in Bash can be ported to almost any Unix-like system and work without any modification needed. Even though it's cross-platform, PowerShell can't touch that level of universality, so you can really only expect it on Windows machines and any others that you control.
I wasn't a fan of the verb-noun naming convention at first, like Get-ChildItem instead of ls, or Set-Location instead of cd. It feels verbose, but I've shortened them with aliases, and have since come to appreciate the clarity of each command, since even users unfamiliar with PowerShell can derive the meaning of almost any cmdlet with a quick glance.
Since most of the scripts I'm writing are for my own systems anyway, the portability perk of Bash doesn't matter much in my home lab, virtual private servers, or daily workstation. The cross-platform version of PowerShell behaves identically on each system I run it on, so I tend to reach for it whenever pipelines grow overwhelming in complex Bash scripts.
As for my Windows systems, running WSL means I can write one PowerShell script that touches Windows APIs and Linux file paths from the same session, without needing to switch tools. That's something Bash simply can't do. There are also no native Bash equivalents for things like error handling (apart from exit codes and set -e, which are notoriously unreliable in pipelines), and credential management (SecureString). These nice-to-haves start to feel essential in longer, more intricate scripts, which just gives me another reason to reach for PowerShell.
It's time to calibrate PowerShell's reputation
Without a doubt, PowerShell isn't going to replace Bash, and it doesn't need to. But it has earned a spot in the toolkit of anyone doing serious scripting work, especially in Windows or hybrid environments. The object pipeline alone is worth the learning curve, and most of the old criticisms are no longer relevant with native builds available on other operating systems. Most Linux users would be surprised by what PowerShell has become. That is, if they ever actually bothered to look.
