Hard disagree. The way Windows handles command line parameters is bonkers. It is one string and every program has to escape/parse it themselve. Yes, there is CommandLineToArgvW(), but there is no inverse of this. You need to escape the arguments per hand and can't be sure the program will really interpret them the way you've intended. Even different programs written by Microsoft have different interpretations. See the somewhat recent troubles in Rust: https://github.com/rust-lang/rust/security/advisories/GHSA-q...
FYI this started out as a vulnerability in yt-dlp [1]. Later it was found to impact many other languages [2]. Rust, along with other languages, also considered it a vulnerability to fix, while some other languages only updated the documentation or considered it as wontfix.
Question of where the pain goes, I guess. In unix, having to deal with shell escaping when doing routine tasks is super annoying -- URLs with question marks and ampersands screwing everything up, and simple expansions (like the `cp *` example above) causing confusing.
Yes, Windows resolution and glob expansion can be inconsistent, but it usually isn't, but Unix makes you eat the cruft every time you use it. And you still get tools like ImageMagick that have strange ad hoc syntax for wildcard because they can't use the standard wildcarding, or even ancient tools like find that force you to do all sorts of stupid shit to be compatible with globbing.
As I understand it, CMD.EXE came from OS/2 and has had many revisions that allow more pervasive evaluation of variables (originally, they were expanded only once, at the beginning of a script).
The .BAT/.CMD to build the Windows kernel must have originally been quite the kludge.
Including pdksh in the original Windows NT might have been a better move.
I quote URLs and "file names" with double quotes in Linux bash much like I quote "Program Files" in Windows cmd. It's the same. I quote spaces\ with\ a\ backslash\ sometimes.
It's really strange to me that Microsoft has never added an ArgvToCommandLineW(). This would solve most of the problems with Windows command line parsing.
PPS: Even less related, there's no exec() in Win32, so you can't write a starter program that does some setup and then runs another program (e.g. specified as a parameter). You need to keep the starter program open and act as a proxy to the started program! See the various dotenv CLI implementations. But I digress.