Exploring the Terminal
Work in a pair, at one machine, and take turns driving. The person who is not typing has the more important job: reading what came back and saying what they think it means.
Nothing here can break anything. You are in a scratch directory full of copies. The worst thing that happens is a command complains at you, and a command complaining at you is the main way anybody learns a shell.
Everything below assumes you are logged in to the CS 70 server. If you are not, Using Lab Machines will get you there, and Finding Your Way Around the Terminal is the page to keep open in another window.
1. Make somewhere to make a mess
mkdir ~/scratch
Everything you produce today goes in there. Today is about trying things, and
trying things makes junk; ~/scratch is where the junk lives so that ~/cs70
stays for actual coursework. At the end of the semester you can delete the
whole directory without having to think about what is in it.
If it tells you the directory already exists, that is fine — you have made it before, and nothing has gone wrong.
2. Get to the playground
cd /cs70/fall2026/lab/week01lab2
ls
The shell is always somewhere. It keeps track of one directory — your current directory — and remembers it between commands. Nothing on screen represents it the way a window or a highlighted folder would, which is why it is easy to forget it exists, but it quietly changes what your commands mean.
ls with nothing after it means "list what is here". cat oliver.txt means
"the oliver.txt that is here". cd is how you go somewhere else, pwd
says where you ended up, and the ~ SERVER > prompt is showing you the same
thing all along.
So when a command says "no such file" about a file you are certain exists, the
answer is almost always that you are standing somewhere else. pwd settles it
in one keystroke's worth of typing.
There is a chunk of text about Oliver Twist in here, and the source code for the three small programs you are about to meet.
I looked inside
meow.cand it is not C++. I do not know any C!
You do not need to. Today these are programs you run, not programs you have to read, and you will meet C properly in CS 105.
C is part of our heritage! Almost everything in that file is perfectly good C++ as well.
And
shuffle.cppin the same directory is C++, and is written to be read, so start there if you want to look at one properly.
You cannot damage this directory, and you do not own it. If you want to change one of these files, copy it to your scratch directory first:
cp oliver.txt ~/scratch/
3. Look at a file three different ways
cat oliver.txt
wc oliver.txt
less oliver.txt
less takes over the screen. Press q to get out.
It has taken over the whole terminal and I do not know how to leave.
q. That is the whole answer, and it works in most things that take over the screen this way.
Talk about it: cat and less both show you a file. When would you
actually want one rather than the other? What did wc give you three numbers
for?
4. Meet two new commands
Run this, exactly as written, with nothing after it:
meow
It sits there. It has not crashed and it is not stuck — it is waiting for input, because that is what this kind of program does. Type a sentence and press Return. Then press Control D on a line of its own to tell it you are finished.
Now try shout the same way.
Both of these are filters. A filter reads from its standard input, does
one small thing, and writes to its standard output. sort, grep, wc and
tr are all filters too. Once you have seen one, you have seen the shape of a
great many Unix commands.
Standard input and standard output are just names for where a program reads and writes when nobody has said otherwise. By default they are both your terminal: standard input is your keyboard, standard output is your screen. Everything in the next two sections is the shell quietly pointing them somewhere else, without the program ever finding out.
Why would anyone write a program that just waits like that?
Because it makes the program useful in situations its author never thought about.
meowdoes not know whether its input is you typing, a file, or another program; it does not have to, and that is the whole trick.
Talk about it: before you run the next section, guess what meow will do
to a number like 1838, and to punctuation. Then find out.
5. Send a file in, and send the result somewhere
The shell can connect a program's input and output to files, using < and >:
meow < oliver.txt
shout < oliver.txt
shout < oliver.txt > ~/scratch/loud.txt
cat ~/scratch/loud.txt
> overwrites without asking. If the file already exists, its old contents
are gone. This is one of the two or three genuinely sharp edges in a shell, and
it is worth meeting it here rather than on your homework.
Talk about it: shout < oliver.txt > loud.txt mentions two files and the
program mentions neither. Where does shout think its input is coming from?
6. Pipes: joining programs together
A pipe, |, takes the output of one program and makes it the input of the
next. Nothing is written to disk in between.
grep -i oliver oliver.txt | meow
Now try both of these, and look carefully at the difference:
shout < oliver.txt | meow
meow < oliver.txt | shout
Talk about it: one gives quiet meows and one gives loud ones, and neither program is behaving inconsistently. What has happened to the capital letters in the first case? Can you say, in one sentence, why order matters in a pipeline?
In the first one,
meowthrows the letters away beforeshoutever sees them.
Exactly. Each stage only ever sees what the stage before it produced, which is the whole idea and also the whole hazard.
There are three streams, not two
Every program starts life with three streams, not two. Alongside standard input and standard output there is standard error, which is where a program sends its complaints.
They are separate on purpose, and you can see why in one command. Ask ls for
a file that does not exist, and send it through shout:
ls nosuchfile.txt | shout
The error message comes back in lower case. shout never touched it,
because it never went down the pipe — it went straight to your screen, past
shout entirely.
That is the point of having a third stream. If errors travelled with the data,
then every pipeline would quietly poison the next stage with its own complaints,
and wc -l would happily count your error messages as lines of output.
If you actually want the error in the pipe, you can say so:
ls nosuchfile.txt 2>&1 | shout
Now it is SHOUTED, because 2>&1 means "send stream 2 to wherever stream 1 is
going". The streams are numbered: 0 is standard input, 1 is standard output,
2 is standard error, and those numbers are why redirection looks the way it
does. Plain > is really 1>; nobody types the 1.
The same split explains something you will meet on your homework:
ls oliver.txt nosuchfile.txt > ~/scratch/mylist.txt
The error still appears on your screen even though you redirected the output,
and ~/scratch/mylist.txt contains only the part that worked.
And here is the thing worth taking away. Look at meow.c in this
directory. It is nineteen lines, and there is nothing in it about files, or
pipes, or terminals — it just reads characters until there are no more. The
program never learns whether it was talking to a keyboard, a file, or another
program. The shell arranges all of that before the program starts, and that
arrangement is what lets nineteen lines be useful in situations its author
never imagined.
7. A third filter, and a pipeline built one stage at a time
Meet shuffle. It puts the lines of its input in a random order.
shuffle < oliver.txt
shuffle is a filter like the other two, but it differs in one important way,
and it is worth seeing why. meow and shout handle one character at a time
and never need to remember anything. shuffle cannot do that: to put the
last line first, you have to have read the last line. So it reads the whole
input before it writes any of it.
Now a real question — what does a passphrase made of four random English words look like? Do not run the finished pipeline. Build it, and after each stage say out loud what changed.
shuffle < /usr/share/dict/words | head -4
shuffle < /usr/share/dict/words | head -4 | tr '\n' '-'
Run the first one a few times. You get different words each time, and a
different shuffle: seed line with them.
That seed line is on standard error, which you met in the deeper dive
above. Look at what that buys you: the seed is on your screen, where you can
read it, and it is not in the pipe, so head -4 never sees it and it cannot
end up in the middle of your passphrase.
Homework 0 asked you to pick a strong password and not something like
goat42. Four random words is one of the standard ways people build one that
is both strong and memorable — so this pipeline is a toy, but it is a toy
version of a real tool.
Now give it the seed instead of letting it choose:
shuffle 1234 < /usr/share/dict/words | head -4
shuffle 1234 < /usr/share/dict/words | head -4
The same four words, every time, for as long as that file does not change.
Talk about it: a shuffle that always gives the same answer sounds useless. When would you actually want one? (Think about two people trying to compare results, or about testing a program that is supposed to behave randomly.)
And then: what happened to the last newline in the tr version, and can
you tell from looking at the screen?
8. The manual is on the machine
Every one of these commands can explain itself:
man shuffle
man wc
Man pages are paged with less, so q gets you out, and / searches.
Try this: using only man sort, work out what sort -u does, and confirm
it by trying it. Nobody is going to tell you the answer; finding it is the
exercise.
Meh. I would just search the web.
Often faster, genuinely. But the manual on this machine describes this version of the command, and the web describes some version on some machine somewhere.
There are eight numbered sections, and
man 3 printfis a different page fromman 1 printf—
Which is real, and is exactly the kind of thing worth knowing on about week nine rather than today.
9. Things to try
Pick whichever appeal. Compare notes with the pair next to you.
- First letters. What letter do most English words begin with?
cut -c1will take the first character of every line, and then you want the samesort | uniq -c | sort -rnidea as before. While you are there: why doesuniqneed its input sorted first, and does leaving thesortout look like an error or like a wrong answer? - A random line, and a random sample.
shuffle | head -1gives you one random line of anything. What else can you point it at? (/etc/passwdandoliver.txtare both on this machine.) - Word frequencies. What are the ten most common words in
oliver.txt? You will wanttr -cs 'A-Za-z' '\n'to get one word per line, and then the samesort | uniq -c | sort -rnidea as before. - Spoilers.
oliver.txthas a line beginningSPOILER. Show the file without it. (grep -vreverses a match.) - Odd words. Find every word in
/usr/share/dict/wordscontaining a doubleu. Then count the ones starting withqthat are not followed byu— there are fewer than you would think, and one of them is barely a word at all. - Three-letter words.
grep "^...$"will do it, and working out why is more interesting than the answer. - How long is a dictionary? And how many of its words does
meowreduce to exactly the same thing?
You will want grep -v, -i, and -f to read the patterns from the
dictionary. You will also need to tell grep that a dictionary word has to
match the whole line rather than appear somewhere in it — and if your
pipeline confidently returns nothing at all, that is the flag you are
missing. A pipeline that returns nothing looks exactly like a pipeline that
found nothing, which is a lesson worth having on a day when the right answer
is known.
If you want to keep going after lab
Not a lab activity — this one is for later, if you enjoyed yourself.
Rewrite meow and shout in C++. Both are short, both are in
week01lab2 for you to read, and shuffle.cpp sitting next to them is a
worked example of the same job done in C++ — so you have a model to copy the
shape from. std::cin.get() and std::cout.put() will do what getchar and
putchar do, and std::cin >> ... is not what you want here, which is
itself worth finding out the hard way.
When you have built one, put it in ~/scratch and use it in a pipeline exactly
as you used ours. A program you wrote is a first-class citizen of the shell
— nothing special had to be arranged, and the shell cannot tell the difference.
That is a surprisingly good feeling, and it is most of the reason this activity
exists.
Before you leave
Find the most surprising thing you learned and tell somebody else in the room about it. Then put it in your lab check-in, in the box that asks what you got up to — that is how it reaches us, and how it reaches next year's version of this page.
Why is it called less?
Because there was already one called more.
more came first. It shows you a screenful of a file, prints a prompt at the
bottom, and waits — the prompt being where the name comes from, since it is
essentially asking whether you would like some more. Try it on something long:
more /usr/share/dict/words
more had one large limitation: it only went forwards. Once a line had
scrolled past, it was gone, and you started again from the top.
less was written as a better more — it can scroll backwards, search, and
jump around. Which left its author with a program that did more than more
and needed a name, and the name its author chose was the joke you would
choose too.
You do not have to take our word for any of this. It is in the manual:
man less
The NAME section reads, in full: less - opposite of more.
Meh. Is the whole system like this?
A fair amount of it, yes.
awkis three surnames,grepis an editor command that escaped, andtaris short for “tape archive” on machines that have not had tapes for forty years.
And
lessis now so much better thanmorethat on many systemsmoreisless, running in a more-compatible mode—
Which is a lovely sentence and we are going to leave it right there.
One practical thing falls out of this. man uses less to show you its
pages, which is why q gets you out of a manual page, and why / searches
inside one. Learning one pager teaches you the other.
(When logged in, completion status appears here.)