🚀 Alguni Start learning

Unit 7: The Shell Is a Language

Variables, questions and loops.

Unit 7 of 8 in Linux and the command line for kids. Its 7 lessons are Remembering Things, Two Kinds of Quotes, The Answer Inside, Doing It to Everything, Asking Questions, Again and Again and Four Hundred Files — 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.

📦 Remembering Things

A box with a name on it

The shell can remember things. NAME=Sam puts Sam in a box called NAME.

To get it back out you put a $ in front: $NAME. The dollar means "not the word NAME — what is *in* NAME".

Terminal

kid@alguni:~$ NAME=Sam
kid@alguni:~$ echo $NAME
Sam
kid@alguni:~$ echo "hello, $NAME"
hello, Sam

No spaces round the equals

This one catches everybody: NAME = Sam does not work.

The shell splits at spaces, so it sees three words and tries to run a program called NAME. Write it with no spaces at all: NAME=Sam.

Terminal

kid@alguni:~$ NAME = Sam
bash: NAME: command not found

Boxes the shell filled in for you

Some are already there when you arrive. $HOME is your home folder, $USER is your name, and $PWD is where you are standing.

env lists the lot. These are how programs find out about you without asking.

Terminal

kid@alguni:~$ echo $HOME
/home/kid
kid@alguni:~$ echo $USER
kid
kid@alguni:~$ cd /tmp
kid@alguni:/tmp$ echo $PWD
/tmp

Try it yourself

What does this print?

Terminal

PET=cat
echo "I have a $PET"

Answer it in the app

💬 Two Kinds of Quotes

They are not the same

Double quotes keep spaces together but still swap $NAME for what is in it.

Single quotes keep everything exactly as typed. No dollars, no wildcards, nothing.

So double quotes are the ones you want almost always, and single quotes are for when you mean the characters themselves.

Terminal

kid@alguni:~$ NAME=Sam
kid@alguni:~$ echo "hello $NAME"
hello Sam
kid@alguni:~$ echo 'hello $NAME'
hello $NAME

The reason you always quote a variable

A filename can have a space in it. If it does, $FILE on its own falls apart — the shell splits it into two words and the command sees two files.

"$FILE" in double quotes stays one thing. This is the single most useful habit in the whole unit.

Terminal

kid@alguni:~$ FILE="my homework.txt"
kid@alguni:~$ ls $FILE
ls: cannot access 'my': No such file or directory
ls: cannot access 'homework.txt': No such file or directory
kid@alguni:~$ ls "$FILE"
my homework.txt

Try it yourself

Which prints the four characters $PET?

  • echo '$PET'
  • echo "$PET"
  • echo $PET
  • echo PET

What comes out?

Terminal

WORD=fish
echo '$WORD'

Answer them in the app

🪄 The Answer Inside

Run this bit first

$(...) runs whatever is inside it and puts the answer in its place.

So echo "there are $(ls | wc -l) files" runs the pipeline first, gets back a number, and prints the sentence with the number in it.

Terminal

kid@alguni:~$ ls | wc -l
3
kid@alguni:~$ echo "there are $(ls | wc -l) files here"
there are 3 files here
kid@alguni:~$ COUNT=$(ls | wc -l)
kid@alguni:~$ echo $COUNT
3

Sums

There is a second kind with two brackets: $(( )) does arithmetic.

It only does whole numbers, so $(( 7 / 2 )) is 3 — the shell throws the remainder away rather than rounding.

Terminal

kid@alguni:~$ echo $(( 2 + 3 ))
5
kid@alguni:~$ echo $(( 7 / 2 ))
3
kid@alguni:~$ N=4
kid@alguni:~$ echo $(( N * N ))
16

Try it yourself

What does this print?

Terminal

echo $(( 10 - 3 * 2 ))

Answer it in the app

🔁 Doing It to Everything

The loop

This is what a terminal is *for*.

for takes a list, puts each thing into a box in turn, and runs the same commands on it. Everything between do and done happens once per item.

Terminal

kid@alguni:~$ for colour in red green blue; do echo "I like $colour"; done
I like red
I like green
I like blue

Written out longer

The semicolons are only there because it is all on one line. In a file you would write it like this instead, and it means exactly the same thing.

for colour in red green blue
do
echo $colour
done

A list of files

The list is usually a wildcard, and now the loop is doing real work: the same job to every file, however many there are.

Notice "$f" in quotes. A filename might have a space in it, and unit 7 lesson 2 is the reason this matters.

Terminal

kid@alguni:~$ for f in *.txt; do echo "--- $f"; cat "$f"; done
--- a.txt
one
--- b.txt
one
two

Try it yourself

What does this print?

Terminal

for n in 1 2 3; do echo $(( n * 10 )); done

Answer it in the app

❓ Asking Questions

if, then, fi

The shell can decide. if runs a test, and if the answer is yes, everything up to fi happens.

fi is if backwards. Somebody in 1977 thought that was funny and we are all stuck with it.

Terminal

kid@alguni:~$ if [ -f notes.txt ]; then echo "the file is there"; fi
the file is there
kid@alguni:~$ if [ -f gone.txt ]; then echo "there"; else echo "not there"; fi
not there

Three questions about a file

[ -f thing ] — is it a file?
[ -d thing ] — is it a folder?
[ -e thing ] — is it there at all?

The spaces inside the square brackets are not optional. [ is really a command, and a command needs a space after its name.

Terminal

kid@alguni:~$ if [ -d a-folder ]; then echo "folder"; fi
folder
kid@alguni:~$ if [ -f a-folder ]; then echo "file"; else echo "not a file"; fi
not a file

Comparing numbers and words

For numbers: -eq equals, -lt less than, -gt greater than.

For words: = and !=.

They look odd, and the reason is that < and > were already taken — by redirection, back in unit 4.

Terminal

kid@alguni:~$ N=7
kid@alguni:~$ if [ $N -gt 5 ]; then echo "big"; else echo "small"; fi
big
kid@alguni:~$ WORD=cat
kid@alguni:~$ if [ "$WORD" = "cat" ]; then echo "it is a cat"; fi
it is a cat

Try it yourself

Why is it -gt and not >?

  • Because `>` already means "send the output to a file"
  • Because the shell cannot do numbers
  • Because `>` is hard to type
  • They both work the same

Answer it in the app

🌀 Again and Again

Keep going while

for runs once per thing in a list. while keeps going for as long as a test is still true.

So something inside the loop has to change, or it never stops.

Terminal

kid@alguni:~$ i=1
kid@alguni:~$ while [ $i -le 3 ]; do echo "line $i"; i=$(( i + 1 )); done
line 1
line 2
line 3

The one that never stops

Forget the line that adds one and i stays 1 for ever. The test is always true, and the loop runs until you stop it.

On a real machine you press Ctrl and C. On this one the shell counts to 5000 and then stops and tells you which loop to look at.

Terminal

kid@alguni:~$ i=1
kid@alguni:~$ while [ $i -le 3 ]; do echo hello; done
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
bash: This program has run 5000 commands and shows no sign of stopping.
A loop that never ends is the usual reason — check the `while`.

Try it yourself

Why does that loop never end?

  • Nothing inside it ever changes `i`
  • The test is wrong
  • `echo` is too slow
  • It needs `done` twice

Answer it in the app

🏆 Four Hundred Files

The promise from lesson one

Right at the start of this track it said: clicking is lovely for one file and horrible for four hundred.

This is where that gets paid off. Everything below would be an afternoon of clicking, and is one line of typing.

Try it yourself

What is the difference between for and while?

  • `for` goes through a list; `while` keeps going until a test stops being true
  • `for` is faster
  • `while` can only count
  • They are the same thing written differently

Answer it in the app