The Unix philosophy is a set of software development concepts and norms which have shaped the way modern software is built.

Initiated in the late 60s and established over time by developers of Unix-like operating systems, the Unix philosophy brought the concepts of modularity and reusability into software engineering best practices.

Douglas McIlroy summarized the Unix philosophy as follows:

  • Write programs that do one thing and do it well.
  • Write programs to work together.
  • Write programs to handle text streams, because that is a universal interface.

Let’s briefly introduce command-line filters and pipelines in order to see how these rules apply within the most popular operating systems.

Introduction to Filters and Pipelines

A filter is a program that gets input data from the standard input and writes output data to the standard output. Filters are frequently used in text processing and are combined together in order to perform more complex text transformations with the use of pipelines.

The latter, are basically sequences of filters separated by the pipe operator (i.e., the vertical bar |), which makes the output of a filter become the input of the next filter in the sequence.

Let’s have a look at a playful example.

A Command-Line Example

Roll a Die

The following one-liner simulates the rolling of a traditional die with 6 faces.

$ seq 1 6 | shuf | head -n 1
3

As the Unix philosophy suggests, it uses three programs that do one single thing (and do it well) by combining them together with pipes.

The table below describes what these programs do.

Command Description
seq 1 6 Prints integer numbers from 1 to 6.
shuf Randomly permutes lines from an input text stream.
head -n 1 Extracts the 1st line from an input text stream.

Let’s break the pipeline apart and see how it works.

First, the command seq produces all the possible outcomes from rolling a die.

$ seq 1 6
1
2
3
4
5
6

Second, the pipe operator | makes the output above become the input of the command shuf. As a result, the outcomes are randomly permuted.

$ seq 1 6 | shuf 
3
2
5
1
4
6

Finally, the command head extracts the 1st outcome from the sequence above. In this example, the result of our simulation is 3.

$ seq 1 6 | shuf | head -n 1
3