🚀 Alguni Start learning

Unit 4: Joining Programs Up

Small tools, plugged into each other.

Unit 4 of 8 in Linux and the command line for kids. Its 6 lessons are Where Output Goes, The Pipe, Sort and Count, Cutting Columns, The Other Stream and The Word Counter — below is everything each one explains, and a question or two from it to try.

Every terminal session on this page was replayed before it shipped, on a machine whose every message is tested against real bash and coreutils.

This unit opens with a fortnight’s trial of everything — no card needed — or with a family plan, bought in the iPhone app. The first two units of every track are free for ever. Try it in the app.

➡️ Where Output Goes

Every program has an out tray

A command does not really "print to the screen". It writes to something called standard output, and by default that happens to be pointed at your screen.

Point it somewhere else and the words go there instead. Nothing about the command changes. It never finds out.

Pointing it at a file

That is all > has ever been. You have been using it since unit 2.

And it works on every command, not just echo — because none of them know where their out tray leads.

Terminal

kid@alguni:~$ ls
a.txt
b.txt
c.txt
kid@alguni:~$ ls > list.txt
kid@alguni:~$ cat list.txt
a.txt
b.txt
c.txt
list.txt

The in tray

There is a tray on the way in as well: standard input. < fills it from a file.

wc -l < guests.txt and wc -l guests.txt count the same lines, but look at what they print. In the second, wc was handed a *name*, so it says the name. In the first it was handed the *words* and has no idea where they came from.

Terminal

kid@alguni:~$ wc -l guests.txt
3 guests.txt
kid@alguni:~$ wc -l < guests.txt
3

Try it yourself

Why did ls > list.txt print nothing?

  • Its output went into the file instead of the screen
  • ls does not work with >
  • It failed
  • The file was empty

Answer it in the app

🪈 The Pipe

Out of one, into the next

If output can go to a file, it can go to another program. That is |, and it is the best idea in Unix.

The left command's out tray is plugged straight into the right command's in tray. No file in between, nothing saved to disk.

Terminal

kid@alguni:~$ ls
a.txt
b.txt
c.txt
d.txt
e
kid@alguni:~$ ls | wc -l
5

Why this is such a big deal

Nobody had to write a "count how many files" program. ls lists things and wc counts lines, and the pipe made a third thing out of them.

That is the whole design: lots of small programs that each do one thing, and a way to join them up. Every command in this course is one of those small programs.

Longer chains

You can keep going. Each | hands its answer on to the next one, left to right, like a relay.

Read this one out loud: list the files, keep the ones with "photo" in the name, count them.

Terminal

kid@alguni:~$ ls | grep photo
photo1.jpg
photo2.jpg
photo3.jpg
kid@alguni:~$ ls | grep photo | wc -l
3

Try it yourself

What does this print?

Terminal

grep red colours.txt | wc -l

In cat log.txt | grep error | wc -l, what does wc actually get?

  • Only the lines that had "error" in them
  • The whole of log.txt
  • The word "error"
  • Nothing — it reads the file itself

Answer them in the app

🔢 Sort and Count

Putting things in order

sort puts lines in order. By default it sorts them as words, which is not the same as sorting them as numbers.

As words, 100 comes before 9, because 1 comes before 9. -n says "these are numbers, treat them as numbers".

Terminal

kid@alguni:~$ sort sizes.txt
10
100
2
9
kid@alguni:~$ sort -n sizes.txt
2
9
10
100

Squashing repeats

uniq throws away a line that is the same as the one right before it. That "right before it" matters: it only ever looks at its neighbour, so you nearly always sort first.

uniq -c counts each group as it squashes it, and that is the trick behind almost every "which is most common?" question you will ever ask.

Terminal

kid@alguni:~$ sort fruit.txt
apple
apple
apple
fig
pear
pear
kid@alguni:~$ sort fruit.txt | uniq
apple
fig
pear
kid@alguni:~$ sort fruit.txt | uniq -c
      3 apple
      1 fig
      2 pear

The famous one

Put those together and you get the pipeline every Linux person knows by heart: sort, squash-and-count, sort by the count, take the top one.

Four small programs. No new program written. That is the point of the whole unit.

Terminal

kid@alguni:~$ sort fruit.txt | uniq -c | sort -n -r
      3 apple
      2 pear
      1 fig
kid@alguni:~$ sort fruit.txt | uniq -c | sort -n -r | head -n 1
      3 apple

✂️ Cutting Columns

A file that is really a table

Lots of files on a Linux machine are tables: one row per line, with the columns split by some character.

/etc/passwd lists everybody who can use this computer. The columns are split by colons, and the first one is the name.

Terminal

kid@alguni:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
kid:x:1000:1000:Kid:/home/kid:/bin/bash

Taking one column

cut takes columns out. -d says what splits them — the delimiter — and -f says which fields you want.

-f1 is the first. -f1,6 is the first and the sixth. -f3- is the third onwards.

Terminal

kid@alguni:~$ cut -d: -f1 /etc/passwd
root
daemon
nobody
kid
kid@alguni:~$ cut -d: -f1,6 /etc/passwd
root:/root
daemon:/usr/sbin
nobody:/nonexistent
kid:/home/kid

Cut, then everything else

cut is another small program, so of course it goes in a pipe. Take a column, sort it, count it.

At this point you are doing something a spreadsheet would take five minutes of clicking to do.

Terminal

kid@alguni:~$ cut -d: -f2 lunches.txt | sort | uniq -c
      3 apple
      1 pear

Try it yourself

What does this print?

Terminal

cut -d: -f2 fruit.csv

Answer it in the app

🚰 The Other Stream

Two trays, not one

Every program has two out trays. Ordinary answers go to standard output. Complaints go to a second one called standard error.

Both land on your screen, which is why you never noticed. But > only catches the first — so an error stays on the screen even when everything else has gone into a file.

Terminal

kid@alguni:~$ cat there.txt missing.txt > out.txt
cat: missing.txt: No such file or directory
kid@alguni:~$ cat out.txt
hello

Why two?

Because otherwise every error message would end up buried in your results.

Imagine ls > list.txt on a folder with a problem in it. If the complaint went into list.txt, your list would quietly have a sentence of English in the middle. Keeping them apart is what makes pipes safe.

Catching the complaints too

2> redirects the second tray. The 2 is its number — output is 1, errors are 2.

And 2>&1 means "send tray 2 to wherever tray 1 is going", which is how you get both in one file.

Terminal

kid@alguni:~$ cat there.txt missing.txt 2> problems.txt
hello
kid@alguni:~$ cat problems.txt
cat: missing.txt: No such file or directory
kid@alguni:~$ cat there.txt missing.txt > all.txt 2>&1
kid@alguni:~$ cat all.txt
hello
cat: missing.txt: No such file or directory

The bin

There is a special file on every Linux machine called /dev/null. Anything written to it disappears, and reading it gives nothing.

So 2> /dev/null means "and be quiet about the errors". It is a real file in a real folder, and it is the tidiest way to say "I do not care".

Terminal

kid@alguni:~$ cat there.txt missing.txt 2> /dev/null
hello
kid@alguni:~$ cat /dev/null

Try it yourself

You run find / -name secret.txt and the screen fills with "Permission denied". How do you hide those?

  • find / -name secret.txt 2> /dev/null
  • find / -name secret.txt > /dev/null
  • find / -name secret.txt | /dev/null
  • You cannot hide them

Answer it in the app

🏆 The Word Counter

One pipeline, five programs

You are going to answer a real question — which word does this book use most? — without writing a program.

Everything you need is already in your hands: tr, sort, uniq -c, sort -n -r, head. The only new one is tr, which swaps characters for other characters.

One word per line

tr translates characters. tr a-z A-Z shouts. tr -d deletes.

The trick for counting words is tr " " "\n": turn every space into a newline, and a paragraph becomes a list.

Terminal

kid@alguni:~$ cat line.txt | tr a-z A-Z
THE CAT AND THE HAT
kid@alguni:~$ cat line.txt | tr " " "\n"
the
cat
and
the
hat

Try it yourself

What is the idea this whole unit is built on?

  • Small programs that each do one thing, joined together
  • One enormous program that can do everything
  • Writing your own program for every question
  • Clicking is faster than typing

Answer it in the app