This commit is contained in:
Miloslav Ciz 2024-03-23 00:26:32 +01:00
parent da70f0a553
commit dc1fe386df
12 changed files with 1771 additions and 1740 deletions

View file

@ -15,9 +15,9 @@ In 1978 [Douglas McIlroy](mcilroy.md) has written a short overview of the Unix s
This has later been condensed into: do one thing well, write programs to work together, make programs communicate via text streams, a universal interface.
Details such as to what extent/extreme this minimalism ("doing only one thing") should be taken are of course a hot topic of many debates and opinions, the original Unix hackers very often very strict, famous example of which is the "cat -v considered [harmful](harmful.md)" presentation bashing a relatively simple function added to the [cat](cat.md) program that should only ever concatenate files. Some tolerate adding some convenience functions to simple programs, especially nowadays.
Details about to what extent/extreme this minimalism ("doing only one thing") should be taken are of course a hot topic of countless debates and opinions, the original Unix hackers are often highly strict, famous example of which is the "cat -v considered [harmful](harmful.md)" presentation bashing a relatively simple function added to the [cat](cat.md) program that should only ever concatenate files. Some tolerate adding a few convenience functions to trivial programs, especially [nowadays](modern.md).
**Simple example**: maybe the most common practical example that can be given is [piping](pipe.md) small [command line](cli.md) utility programs; in Unix there exist a number of small programs that do *only one thing but do it well*, for example the [`cat`](cat.md) program that only concatenates and outputs the content of selected files, the [`grep`](grep.md) program that searches for patterns in text etc. In a command line we may use so called [pipes](pipe.md) to chain some of these simple programs into more complex processing pipelines by redirecting one program's output stream to another one's input. Let's say we want to for example automatically list all first and second level headings on given webpage and write them out alphabetically sorted. We can do it with a command such as this one:
**Simple example**: likely the most common practical example that can be given is [piping](pipe.md) small [command line](cli.md) utility programs; inside a Unix system there live a number of small programs that do *only one thing but do it well*, for example the [`cat`](cat.md) program that only concatenates and outputs the content of selected files, the [`grep`](grep.md) program that searches for patterns in text etc. In command line we may use so called [pipes](pipe.md) to chain some of these simple programs into more complex processing [pipelines](pipeline.md) by redirecting one program's output stream to another one's input. Let's say we want to for example automatically list all first and second level headings on given webpage and write them out alphabetically sorted. We can do it with a command such as this one:
```
wget -q -O - "http://www.tastyfish.cz/lrs/main.html" | grep -i -o "<h[12][^>]*>[^<]*<" | sed "s/[^>]*> *\([^ ][^<]*[^ ]\) *<.*/\1/g" | sort
@ -35,11 +35,11 @@ Welcome To The Less Retarded Wiki
What Is Less Retarded Software/Society/Wiki?
```
In the command the pipes (`|`) chain multiple programs together so that the output of one becomes the input of the next. The first command, *[wget](wget.md)*, downloads the [HTML](html.md) content of the webpage and passes it to the second command, *[grep](grep.md)*, which filters the text and only prints lines with headings (using so called [regular expressions](regex.md)), this is passed to *[sed](sed.md)* that removes the HTML code and the result is passed to *sort* that sorts the lines alphabetically -- as this is the last command, the result is then printed out, but we could also e.g. add ` > output.txt` at the end to save the result into a text file instead. We also use [flags](flag.md) to modify the behavior of the programs, for example `-i` tells *grep* to work in case-insensitive mode, `-q` tells *wget* to be silent and not print things such as download progress. [This whole wiki](lrs_wiki.md) is basically made on top of a few scripts like this (compare e.g. to [MediaWiki](mediawiki.md) software), so you literally see the manifestation of these presented concepts as you're reading this. This kind of "workflow" is a fast, powerful and very flexible way of processing data for anyone who knows the Unix tools. Notice the relative simplicity of each command and how each one works as a **[text](text.md) [filter](filter.md)**; text is a universal communication interface and behaving as a filter makes intercommunication easy and efficient, utilizing the principle of a [pipeline](pipeline.md). A filter simply takes an input stream of data and outputs another stream of data; it ideally works on-the-go (without having to load whole input in order to produce the output), which has numerous advantages, for example requiring only a small amount of memory (which may become significant when we are running many programs at once in the pipeline, imagine e.g. a server with 10000 users, each one running his own commands like this) and decreasing [latency](latency.md) (the next pipe stage may start processing the data before the previous stage finishes). When you're writing a program, such as for example a [compression](compression.md) tool, make it work like this.
In the command the pipes (`|`) chain multiple programs together so that the output of one becomes the input of the next. The first command, *[wget](wget.md)*, downloads the [HTML](html.md) content of the webpage and passes it to the second command, *[grep](grep.md)*, which [filters](filter.md) the text and only prints lines with headings (using so called [regular expressions](regex.md)), this is passed to *[sed](sed.md)* that removes the HTML code and the result is passed to *sort* that sorts the lines alphabetically -- as this is the last command, the result is then printed out, but we could also e.g. add ` > output.txt` at the end to save the result into a text file instead. We also use [flags](flag.md) to modify the behavior of the programs, for example `-i` tells *grep* to work in case-insensitive mode, `-q` tells *wget* to be silent and not print things such as download progress. [This whole wiki](lrs_wiki.md) is basically made on top of a few scripts like this (compare e.g. to [MediaWiki](mediawiki.md) software), so you literally see the manifestation of these presented concepts as you're reading this. This kind of "workflow" is a fast, powerful and very flexible way of processing data for anyone who knows the Unix tools. Notice the relative simplicity of each command and how each one works as a **[text](text.md) [filter](filter.md)**; text is a universal communication interface and behaving as a filter makes intercommunication easy and efficient, utilizing the principle of a [pipeline](pipeline.md). A filter simply takes an input stream of data and outputs another stream of data; it ideally works on-the-go (without having to load whole input in order to produce the output), which has numerous advantages, for example requiring only a small amount of memory (which may become significant when we are running many programs at once in the pipeline, imagine e.g. a server with 10000 users, each one running his own commands like this) and decreasing [latency](latency.md) (the next pipe stage may start processing the data before the previous stage finishes). When you're writing a program, such as for example a [compression](compression.md) tool, make it work like this.
Compare this to the opposite [Windows philosophy](windows_philosophy.md) in which combining programs into collaborating units is not intended, is possibly even purposefully prevented and therefore very difficult, slow and impractical to do -- such programs are designed for manually performing some predefined actions, mostly using [GUI](gui.md), e.g. painting pictures with a mouse, but aren't made to collaborate or be automatized, they can rarely be used in unintended, inventive ways needed for powerful [hacking](hacking.md). Getting back to the example of a compression tool, on Windows such a program would be a large GUI program that requires a user to open up a file dialog, manually select a file to compress, which would then probably go on to load the whole file into memory, perform compression there, and the write the data back to some other file. Need to use the program on a computer without graphical display? Automatize it to work with other programs? Run it from a script? Run it 10000 at the same time with 10000 other similar programs? Bad luck, Windows philosophy doesn't allow this.
Compare this to the opposing [Windows philosophy](windows_philosophy.md) in which combining programs into collaborating units is not intended, is possibly even purposefully prevented and therefore very difficult, slow and impractical to do -- such programs are designed for manually performing some predefined actions, mostly using [GUI](gui.md), e.g. painting pictures with a mouse, but aren't designed to collaborate with each other or be automatized, they can rarely be used in unintended, inventive ways needed for powerful [hacking](hacking.md). Returning to the example of a compression tool, on Windows such a program would be a large GUI program that requires a user to open up a file dialog, manually select a file to compress, which then might even do nasty things like loading the whole file into memory (because anyone who can afford Windows can also afford a lot of [RAM](ram.md)), perform compression there, and then writing the data back to some other file. Need to use the program on a computer without graphical display? Automatize it to work with other programs? Run it from a script? Run it 10000 at the same time with 10000 other similar programs? Bad luck, Windows philosophy doesn't allow this.
**Watch out! Do not misunderstand Unix philosophy.** There are many extremely dangerous cases of misunderstanding Unix philosophy by [modern](modern.md) [wannabe programmers](soydev.md) who can't tell [pseudominimalism](pseudominimalism.md) from true [minimalism](minimalism.md). One example is the hilarious myth about "[React](react.md) following Unix philosophy" ([LMAO this](http://img.stanleylieber.com/src/20872/img/small.1527773532.png)), the devs just show so many misunderstandings here -- firstly of course [JavaScript](js.md) itself is extremely [bloated](bloat.md) as it's a language aiming for things like comfort, rapid development, "safety" and beginner friendliness to which it sacrifices performance and elegance, an expert hacker trying to write highly thought through, optimized program is not its target group, therefore nothing based on JavaScript can ever be compatible with the Unix way in the first place. Secondly they seem to imply that basically any system of modules follows Unix philosophy -- that's of course wrong, modularity far predates Unix philosophy, Unix philosophy is more than that, merely having a package system of libraries, each of which focuses on some thing (even very broad one like highly complex [GUI](gui.md)), doesn't mean those tools are simple (both internally and externally), efficient, communicating in good ways and so on.
**Watch out! Do not misunderstand Unix philosophy.** There are many extremely dangerous cases of misunderstanding Unix philosophy by [modern](modern.md) [wannabe programmers](soydev.md) who can't tell [pseudominimalism](pseudominimalism.md) apart from true [minimalism](minimalism.md). One example is the hilarious myth about "[React](react.md) following Unix philosophy" ([LMAO this](http://img.stanleylieber.com/src/20872/img/small.1527773532.png)), the devs just show so many misunderstandings here -- firstly of course [JavaScript](js.md) itself is extremely [bloated](bloat.md) as it's a language aiming for things like comfort, rapid development, "safety" and beginner friendliness to which it sacrifices performance and elegance, an expert hacker trying to write highly thought through, optimized program is not its target group, therefore nothing based on JavaScript can ever be compatible with the Unix way in the first place. Secondly they seem to imply that basically any system of modules follows Unix philosophy -- that's of course wrong, modularity far predates Unix philosophy, Unix philosophy is more than that, merely having a package system of libraries, each of which focuses on some thing (even very broad one like highly complex [GUI](gui.md)), doesn't mean those tools are simple (both internally and externally), efficient, communicating in good ways and so on.
**Does Unix philosophy imply [universality](universality.md) is always bad?** Well, most likely no, not in general at least -- it simply tells us that for an expert to create art that reaches the peak of his potential it seems best in most cases if he lives in an environment with many small, highly efficient tools that he can tinker with, which allow him to combine them, even (and especially) in unforeseen ways -- to do [hacking](hacking.md). Universal tools, however, are great as well, either as a supplement or for other use cases (non-experts, quick dirty jobs and so on) -- after all a general purpose [programming language](programming_language.md) such as [C](c.md), another creation of Unix creators themselves, is a universal tool that prefers generality over effectiveness at one specific task (for example you can use C to process text but you likely won't match the efficiency of [sed](sed.md), etc.). Nevertheless let us realize an important thing: a universal tool can still be implemented in minimalist way, therefore never confuse a universal tool with a bloated monolith encumbered by feature creep!