<p><pre><code> Unix permits programs to communicate with one another, and with the user,
exclusively through character streams. You can’t write a function that
returns a list of files because the shell doesn’t know what a “list” is,
doesn’t know what “files” are, and couldn’t tell you the difference between
a “function” and a “program” if its life depended on it. Programs don’t
“take arguments” and “return values”, they read characters from stdin and
print characters to stdout!
</code></pre>
And this is why I consider PowerShell a more Unix-y shell than bash. Powershell commands don't just operate on character streams. They operate on CLR <i>objects</i>. For example, the PowerShell equivalent of grep, Select-String, doesn't return a string, or even a list of strings. It returns a list of match objects, which contain the regexp used, the matching string, and the file that matched. PowerShell often gets dinged for its verbosity, but honestly, I find it much easier to compose PowerShell commands because I know exactly what each command does, and the command-line flags are mostly intuitive. Meanwhile, Unix commands are shorter, yes, but it's a lot more difficult for me to remember, e.g. that if I want to run a command across a number of files, I have to pass the command to find.
Deciding whether a program does "one thing well" is a matter of granularity. `ls` with its 38 flags is absolutely tiny compared to, say, finder, which displays multimedia previews, allows you to connect to remote servers, and probably does a bazillion other things.<p>Yes, `ls` isn't <i>perfectly</i> clean in a mathematical sense, but it's still tiny compared to modern software, and passing a couple of flags for common tasks now and then is far more convenient than writing `ls | map ... | sort ...`.<p>Unix is not a mathematically perfect Unix, but it is most definitely an acceptable one.
What's funny is that some modern scripting languages like Python, with things like the "os" module, are <i>almost</i> passable as a general purpose shell scripting environment. I actually tend to write Python scripts instead of bash shell scripts for one-off file manipulation scripting, mostly because even after a decade-plus long career, I've never become much of a wizard at bash shell staples like sed or awk.<p>But it's just that a general purpose programming language like Python doesn't treat executing subprocesses in enough of a first-class manner, in the way the bash shell does, to make it feel like a seamless shell-scripting experience. You still have to go through the motions of "import os", etc. just to get started, and you can't directly execute other programs, instead having to use "system" or the more cumbersome subprocess module. But still, it's.... tantalizingly close to something like a "better" shell that includes support for lists and other data structures instead of just "everything is a string".
"Unix considered harmful"<p>I think "a demonstrably inhumane environment" may be my favourite description to date.<p>There are many terrible assumptions in the design of the shell. Not least:<p>Use short commands (because they're quicker to type in theory, even though you'll waste time huge amounts of time in practice looking up commands and switches, because even the average god-like greybeard can't remember more than a few tens, and beginners have no chance)<p>Use terse switches (ditto)<p>Text is universal and computers are text processors (not true back then, even less true now)<p>Make no attempt at standardisation (switches are effectively random between different commands)<p>Quick hacks are better than a smart and structured environment (this was always bullshit and has caused endless grief, not just in Unix, but in everything touched by Unix)<p>Software forks are good (not in the shell, they're not)<p>And now computing is buried under the dead weight of accumulated cruft and poor theory and practice - probably forever.<p>But that isn't even the real problem. The real problem is that research into humane OS design seems to have stalled. CS academics could band together to design something smarter, better, and friendlier than the current shell. But there seems to be zero interest in starting a project that would generate huge productivity and reliability gains and also make low-level computing more accessible to ordinary users.<p>I find that baffling, and actually rather disturbing.
It seems that the lessons of Rob Pike's 1983 talk "cat -v Considered Harmful" have still not been absorbed 34 years later. Here is the abstract of the talk, together with the link to the paper (co-authored with Brian Kernighan) that evolved from it: <a href="http://gaul.org/files/cat_-v_considered_harmful.html" rel="nofollow">http://gaul.org/files/cat_-v_considered_harmful.html</a>
There was a time (PWB Research Unix) when one typed:<p><pre><code> ls | sort | mc
</code></pre>
to get an alphabetical list in multiple columns. That didn't last.<p>This reads like someone discovered functional programming and now wants everything to be functional.
Unix is a poor implementation of the Unix philosophy. Just like QWERTY is an awful keyboard layout, etc. This is yet another case where we are steeped in tradition. It would be fantastic if we could just instantly overcome these shortcomings, but it's difficult enough to make an OS compatible with the ones we already have. With manufacturers like Nvidia and Broadcom keeping such a tight control over their drivers, it's difficult enough to even make an OS!<p>It would be fantastic to have a more cohesive environment, especially in (and including) the shell, but most people are happy with the status quo.<p>Even worse than *nix tools, there is really no environment outside the realm of text-based UI that follows the Unix philosophy. A GUI that does just one thing, let alone well? Ha. AFAIK, there is no existing way to create GUI software that can cohesively inter-operate with the expressive power that pipes and subshells give command-line tools.
I think the unix design philosophy is great in theory, but in practice you get a lot of parts that have to be combined, this combination then gets tricky, so you will want a utility that just covers all the edges.<p>Lets see, I often use ls -tr<p>* the good thing about this is that it is very fast to type<p>* the bad part is that you have to memorize the incantation.<p>You could probably do it by a pipe (ls | sort <now it gets complicated here>)<p>* good: the good part is that every program does its job<p>* bad: also two programs have a larger footprint than one<p>* good: you can have it as an alias to make it short again<p>* bad: aliases can't be used in bash scripts, unless you explicitly source the file that defines the alias<p>* good/bad: you just shifted complexity from ls to sort<p>....
Back in 1983 the authors of UNIX were already complaining about the proliferation of incompatibilities. As far as "true unix" is concerned nothing this paper refers to is considered "true unix".<p><pre><code> It seems that UNIX has become the victim of cancerous growth at the hands of
organizations such as UCB. 4.2BSD is an order of magnitude larger than Version
5, but, Pike claims, not ten times better.
</code></pre>
<a href="http://harmful.cat-v.org/cat-v/" rel="nofollow">http://harmful.cat-v.org/cat-v/</a>
What always gets me about this class of articles is that they are a classic case of bikeshedding. Is anyone <i>really</i> having that much trouble with ls?<p>Yes, things like ls could be better - but is switching between "ls --plus -a --pile --of --options" and "ls | one | damn | filter | after | another" a particularly core concern?<p>I tend to agree with this bit... "Rather than re-evaluating the Unix command line with an eye towards improving its usability under the greatly relaxed technological constraints of modern hardware, we’ve written terminal emulators that faithfully reproduce the constraints of the mid-1970s",<p>... but feel that the author decided that it was a lot more fun and easy to complain about ls instead of properly exploring this idea.
I think in some ways using flags to modify the behavior of a command is an elegant solution. The alternative is to rewrite a new version of "ls" for each sort of functionality you'd like.<p>Without flags you'd need "ls1", "ls2" etc. like you do with system calls ala. dup()->dup2()->dup3(), pipe() -> pipe2() etc.<p>Linux has gone further than some *nixs and started using flags to extend system calls as well see:
<a href="https://lwn.net/Articles/585415/" rel="nofollow">https://lwn.net/Articles/585415/</a>
>...it was developed by and for a small group of highly specialized experts in an environment where every keystroke, every character displayed on the screen, came at a real and meaningful cost.<p>Have keyboards gotten better/faster? How does the existence of a 80 character line length change the best way to specify a directory listing?<p>This seems to be based on the logical fallacy that since the old thing is bad that a better new thing must be possible.
The arguments of ls are simply an optimization for things which are done so frequently that simply typing them over and over becomes a huge waste of time. In the early days, you can imagine people first typing everything out manually, then creating macros like 'ls | awk {stuff} | sort -k2 |..." and then just getting fed up with your .xxxrc file and modifying the ls source to trim it down to a couple of arguments.<p>Taken to extremes, this article seems to suggest that all command line flags for every executable ought to be replaced with separate executables and pipes. Just imagine how many files would be in /usr/bin, and how many of them you would have to remember just to do useful work every day. We'd have to increase inode limits just to hold all the manpages. An OS like this would not be one I'd like to use.
Lisp machines once had all it took to make better interfaces but were wiped out by the worse-is-better logic behind Unix. Now the weight of all the stuff we built on top of that makes it harder to change. And almost everyone still subscribes to worse-is-better, albeit under a different name.
I do a lot of things from the command line. But as soon as I have a few lines and I need to write a script I just switch to Perl(which I know better than Python). It just seems easier. I still call unix commands but Perl seems better to glue them together.
What's the problem with all those options? IMHO ls is not bloated at all. It simply follows the Unix philosophy: Do just <i>one</i> thing, and do it "right" which means: do it as well as possible. ls actually does that. I never had any desire for another ls because ls already gives me almost all possible functionality. I am glad that I have all those options so that I don't have to write my own tool to get a special function if I really need that.<p>If you don't need all the options, ignore them. If ls is too complicated for you then do just as the author recommends: "write a simpler alternative to ls", and name it lf ("list files") or the like.
> Unix permits programs to communicate with one another, and with the user, exclusively through character streams.<p>It communicates using byte streams. For the original authors of Unix where ascii ruled supreme, it didn't make a difference but now it does. For example, see this stack question: <a href="http://unix.stackexchange.com/questions/167814/get-first-x-characters-from-the-cat-command" rel="nofollow">http://unix.stackexchange.com/questions/167814/get-first-x-c...</a>