Is efficiency the biggest problem?
It seems to me the bigger problem is that streams of raw bytes over pipes is the wrong level of abstraction for most tasks; at least we seem to have decided that is the case when we are writing code within a program, so I don't see why it shouldn't extend to interprocess programming. I don't see people recommending only defining functions that accept single dimensional arrays of bytes (rather than strings and trees and hashmaps and multidimensional arrays and so on), even when programming in C.
You end up with every tool containing code to parse a stream of bytes into the appropriate data structures, and then probably also write them out to a stream of bytes too. The user has responsibility for a lot of data munging too. It is error prone and repetitive, at least when dealing with anything other than very simple text files containing lines of strings where you know which encoding has been used. (Re)using libraries that read and write more structured data is likely to get you flamed[1]. The history of Unix contains plenty of security problems due to people not correctly accounting for nulls or control characters or spaces etc when chaining together commands (although this is more of a problem with shells than pipes themselves). The output is often not friendly to human eyes by default (I'm thinking of things like localised date and time formats, number formats and so on) since it has to be suitable for passing to another program, unless you use more options or another tool to reformat it.
I would compare it to working with raw memory in C. It's the lowest common denominator, you can do anything, but it's also trivial to screw up and there is a high cognitive overhead. Perhaps it's just too hard to introduce anything higher level at this point.
Perhaps my opinion would change if I spent years (deeply) learning unix tools, but maybe that would just be because I had invested so much time learning a complicated system.
Unix pipes are effectively the same thing as using text streams in C.
Granted not quite the same thing, but raw bits are often used in lower level languages. Take Windows Win32 APIs, there's a lot of instances where styles are defined by adding constants with values being exponentials of 2. Thus creating a binary array of boolean states.
Another example I used to run into was Windows' controller (joystick et al) API (again Win32). Each bit would represent a different controller button and the 'on' state was if the button was depressed. But as the value was returned as an unsigned long int (if memory serves), it was up to the developer to write their own parser to convert what would otherwise been a random number into a meaningful array of bits. (or at least I did - there is a chance I overlooked another function as this was before I made the switch to DirectX6 - so many years ago!)
You end up with every tool containing code to parse a stream of bytes into the appropriate data structures, and then probably also write them out to a stream of bytes too. The user has responsibility for a lot of data munging too. It is error prone and repetitive, at least when dealing with anything other than very simple text files containing lines of strings where you know which encoding has been used. (Re)using libraries that read and write more structured data is likely to get you flamed[1]. The history of Unix contains plenty of security problems due to people not correctly accounting for nulls or control characters or spaces etc when chaining together commands (although this is more of a problem with shells than pipes themselves). The output is often not friendly to human eyes by default (I'm thinking of things like localised date and time formats, number formats and so on) since it has to be suitable for passing to another program, unless you use more options or another tool to reformat it.
I would compare it to working with raw memory in C. It's the lowest common denominator, you can do anything, but it's also trivial to screw up and there is a high cognitive overhead. Perhaps it's just too hard to introduce anything higher level at this point.
Perhaps my opinion would change if I spent years (deeply) learning unix tools, but maybe that would just be because I had invested so much time learning a complicated system.