I call it "failure by success". Unix is so incredibly successful that we are bound by decisions made 40 years ago.
There is an unbroken chain from the Thompson shell circa 1972 to modern day bash.
The language wasn't designed; it was accreted over decades.
Looking at the difficulty of the Python 2 -> 3 transition might give you an idea of how hard it is to make incompatible changes, so that's what we're stuck with.
It's a little bit like asking why C has so many warts -- e.g. the insecure standard library, "holes" in the type system like silently converting pointers to bools.
But it's easier to "clean up" compiled languages than interpreted languages, and it was somewhat done with C89, C99, etc. You can have different compilation modes, and the user is more likely to fix things that a compile error flags.
With something like shell, you don't have a good chance to surface errors and clean up corner cases. It just evolved over time until it was out of control.
The language wasn't designed; it was accreted over decades.
Looking at the difficulty of the Python 2 -> 3 transition might give you an idea of how hard it is to make incompatible changes, so that's what we're stuck with.
It's a little bit like asking why C has so many warts -- e.g. the insecure standard library, "holes" in the type system like silently converting pointers to bools.
But it's easier to "clean up" compiled languages than interpreted languages, and it was somewhat done with C89, C99, etc. You can have different compilation modes, and the user is more likely to fix things that a compile error flags.
With something like shell, you don't have a good chance to surface errors and clean up corner cases. It just evolved over time until it was out of control.
I'm working on fixing that with my Oil project: http://www.oilshell.org/blog/2018/01/28.html