I realise the below comment is going back a few weeks... but I didn't realise it when I started writing my reply. Accidentally just resumed the thread at the point I'd last looked at it. But have written it and will post it!
The real reason I prefer Linux isn't because it's problem free but because it has capabilities I appreciate that Windows does not. I use the terminal daily to do a variety of things that wouldn't be easy to do on Windows. Linux feels like/is a proper tool I can use to get what I want done, whereas Windows felt like dealing with an opaque bureaucracy that made its own decisions about what I was and wasn't allowed to do and I loathe it. Again it's about what you want to do with your system. The things I do are far easier (or even possible at all) on Linux than Windows so naturally I'm more happy with it.
I sort of want to debate you a little on this. I grew up on Bash and Vi and for a long time the lack of proper terminal, propert scripting and indeed needing OS elements exposed to be controlled even with those things, was a a major lack on Windows. That last one is wholly addressed as every operation and configuration of the Windows OS that I can think of is now exposed as an object. This is incalculably useful. As to the proper terminal and scripting well Windows terminal still has a few niggles that throw me. For example the lack of global history from session to session - it sort of has this but it's too clunky to get into here. Or that when I open a new tab it defaults to the initial location rather than wherever I am in the current terminal - which is how every Bash terminal I use is configured. And perhaps the biggest issue being that getting an in-terminal editor a la Vi is a nightmare. Though I've sort of made my peace with Visual Studio now (no I haven't). So I'm not here to evangelise the Windows terminal in a Linux thread - it still throws me. But it's decent enough and it certainly has a lot of features these days. But I would like to delve into the script side a bit more.
I will sincerely argue that Powershell is superior to Bash. Part of that is that Windows OS exposes every part of itself as an object and Powershell support for object pipelining as opposed to Bash's text mangling fits well with Windows whereas it wouldn't fit as well on Linux just as Bash isn't a good fit on Windows (sorry Cygwin).
But the other part is that Powershell really is functionally superior to Bash and infinitely more consistent. To take one simple example, how is it that the
find command has a built in print formatter? Which is has different syntax to the actual print command? And don't get me started on
Awk. Whereas lets say I want to format the output of something in Powershell? I could pipe a set of file objects from one command directly to the
ConvertTo-CSV or
ConvertTo-JSON cmdlets. Just the same as if I were reading a list of ACLs I could again pipe to ConvertTo-CSV or ConvertTo-JSON and know that these tools just receive the objects themselves, no text-mangling by the provider to control a format. It's all very logical and consistent and for the most part, easy enough to remember. It's ironic but Powershell actually follows the Unix philosophy of "Do one thing and do it well" much more than GNU tools do such as find.
In fact, lets roll with an example along these lines to show what I mean. I'm not trying to slate Bash, tbc. But I am challenging the idea that Windows limits you. I think working through some equivalents in both is interesting.
Lets say I want to recursively search the current directory for files containing a certain string. That's a realistic example. In GNU/Linux I'm looking at this:
grep -rl myString *
Straight forward enough if you know the commands. There are a few ways of doing this in PS but lets go with this:
Get-ChildItem -Recurse *.* | Where-Object { (Select-String 'myString' $_) } | Select-Object -Property FullName
First thing you notice? It's a lot longer. It's
mostly fairly intuitive, though.
Get-ChildItem isn't a name you'd guess if you had no familiarity at all but then neither is
grep. And
Get-ChildItem is at least consistent with the many other
Get-* commands you'll learn.
The
Where-Object is obviously a filter. It returns objects where the clause evaluates to True. I put a Select-String cmdlet in there. Again, not something you'd magically know but easy enough to remember and probably the only thing that really needs to be explained if you're unfamiliar with PowerShell is the $_. That's the placeholder for the input, like string interpolation. Easy enough concept for anybody who can use Awk.

In any case, this highlights the more modular nature of Powershell. People are so used to grep being both the file search AND the pattern matching that they forget they're really two separate operations. But it makes for more consistency and flexibility for operations to have separation of concerns.
Anyway to return to the example you could stop after the Where-Object command but you'd get back a list of file objects which might not have the formatting you want, e.g. would have timestamps, permissions, whatever. So I put a Select-Object -Property on the end which will get just the FullName, i.e. path and filename. Again, none of this is something you'd magically just know but it's all delightfully modular. I can send any object to the Select-Object -Property blah and have it handle the input. Or I could have the end piece be that ConvertTo-CSV that I mentioned, for example. Or whatever else. Contrast with Awk and its text slicing based on fragile text format.
Anyway, tl;dr: that's an equivalent in powershell to
grep -rl mystring *
in GNU/Linux. It's longer but arguably more intuitive and cmdlets expose their specifications to the shell itself so the terminal knows what parameters it supports so the terminal can underline errors, detect typos, handle autocomplete of them and so forth. Bash will autocomplete grep but it can't autocomplete the options because GNU/Linux commands aren't built in a standard way to have such definitions.
Anyway, lets go on a bit from there. Lets say I don't just want a list of matching files. Lets say I want their last modified date as well.
I'm going to have to fundamentally change my approach in GNU/Linux because the output of grep is just text in a specific format. It doesn't contain the information I need. I am rusty with Bash so if there's an easier way to do this let me know. But here's something getting not just the matching files but with their modified dates:
grep -rl myString | xargs stat -c %n':'%z | awk -F: '{print $1, $2}'
Here I'm having to text mangle and then feed the filenames back into another command and then the textual format of that command text mangled into another. The
xargs section has to have its input in a specific expected pattern. I couldn't for example just swap in a different preceding command and know it would work. It's fragile. Ditto to the awk command, I have to have a specific textual input format. Lets contrast that with Powershell:
Get-ChildItem -Recurse *.* | Where-Object { (Select-String 'myString' $_) } | Select-Object -Property FullName, LastWriteTime
See, the sole change I made was to add an additional property,
LastWriteTime onto the end and I can do that because I'm not passing text around but the actual file objects. Everything is already there and isn't sensitive to the particular text format used by some predecessor in the chain. Though if I did violate the robustness say, by passing an object that didn't have a LastWriteTime property, I would get a proper Exception raised which is better and I can handle programatically.
Lets take it further still. Lets say I want to search for matching files but only in those modified in the last twelve months. Again, it's a fairly simple and intuitive change in Powershell:
Get-ChildItem -Recurse *.* | Where-Object { (Select-String 'myString' $_) -and $_.LastWriteTime -gt (Get-Date).AddMonths(-12) } | Select-Object -Property FullName, LastWriteTime
All I've done is added an extra condition to the Where-Object filter. Job done. Lets see what's going on in Bash world:
Well again, I'm going to have to change my approach again I think. I don't want to filter on the end of my chain because firstly I probably have to write a full on Bash script and secondly that's not remotely performant to read everything in and just filter stuff out based on text at the end. So again tell me if there's a better way to do this but what I think is this:
find /directory -type f -mtime -365 -print0 | xargs -0 grep -l myString | xargs stat -c %n':'%z | awk -F: '{print $1, $2}'
Is there anything wrong with that other than it being long and maybe requiring you to remember some unintuitive command and formatting details? Actually yes - at each stage you're going back to the file system to request new information because it's just passing along text and each command is having to receive it, parse it, then use it to look up the actual file. Contrast that with Powershell where it accesses the file system once at the start and then just operates on it at each stage in memory (unless the list were *very* large).
So this post got a lot longer than I planned. It was going to be just a quick comment along the lines of "Windows can do this too" but then I decided to add an example to show what I meant and it got away from me. I know this is the Linux thread. I like Linux, I use Linux. Not meaning to start a Windows vs. Linux debate. They're both good. But Windows has caught up to Linux in many ways and I think some of the more devoted Linux users don't realise that. Honestly the main flaws with Windows these days are poor support for huge numbers of cores and, well, everything Microsoft forces into it for marketing / business reasons.