LearnLinux FoundationsI/O Redirection

Input Redirection

< - a hands-on Linux lab on a real virtual machine.

Feed a file into a command's stdin with the < operator. The shell opens the file, the command reads a nameless stream, and the output proves it: wc -l < fruits.txt prints just the count, no filename. Drilled on wc and sort in the practice terminal.

Run the same counting command on the same file, two slightly different ways, and the shell hands back two different answers. One answer is 5 fruits.txt. The other is just 5. Same file, same count, but in the second one the filename has vanished.

Where did the name go? That missing word is not a glitch. It is the clearest window into how the shell feeds programs their input. By the end of this lesson you will make it disappear on purpose, with one character: <.

The black boxes below are a practice terminal: a safe sandbox that checks the one command each step teaches, so you cannot break anything. On the real machine at the end of the module, the capstone mission builds this same signal folder and you run these moves for real.

Your workspace is the same signal folder this module always uses, with fruits.txt, colors.txt, numbers.txt, and the script report.sh inside. The prompt below reads ~/signal, which means the shell is standing inside that folder, so a plain name like fruits.txt finds the right file.

Meet the test subject first. cat prints a file's contents; it had its own lesson back in Reading Files:

cat fruits.txt

prompt: student@linuxcamp:~/signal$ answer: cat fruits.txt output: apple banana cherry date elderberry hint: cat, a space, then the filename: cat fruits.txt

Five fruits, one per line. Keep that number in your head: five lines. Both counting commands in this lesson will find it, but they will report it differently.

Remember the three channels from the File Descriptors lesson. Every command is born with stdin (channel 0) for input, stdout (channel 1) for results, and stderr (channel 2) for errors. With > and >> you re-pointed channel 1 away from the screen and into files. Both of those steer output.

This lesson steers the opposite direction. By default, channel 0 is connected to your keyboard: when a command wants input, it reads what you type. The less-than sign < re-points channel 0 at a file instead. The shell opens the file and pours its contents into the command's stdin, exactly as if you had typed every line yourself. The command cannot tell the difference, and that blindness explains the missing filename.

Redirection is as old as Unix itself. The < and > operators were already in the first Unix shell in 1971, two years before the pipe was invented, and the syntax has not changed since.

wc -l counts lines; you met it in the Reading Files section. The familiar way to use it is the argument form: hand it the filename directly, and wc opens the file itself.

Before you run it, commit to a prediction: will it print just the count, or the count plus something else?

wc -l fruits.txt

prompt: student@linuxcamp:~/signal$ answer: wc -l fruits.txt output: 5 fruits.txt hint: wc -l, a space, then the filename as an argument: wc -l fruits.txt

Two things came back: the count, 5, and the name, fruits.txt. That name is the tell. wc opened the file itself, so it knows what the file is called and reports the name next to the count. Remember both halves of that output. You are about to make one of them disappear.

Here is the same count, written with the < operator: wc -l < fruits.txt. The shell sees the <, opens fruits.txt, wires it to channel 0, and then runs wc -l with no filename at all. The shell does the opening; wc just reads its input stream until the stream ends.

Watch where the data flows. The file pours into wc through stdin, and the count flows on to your screen:

{ "caption": "wc -l < fruits.txt: the < operator re-points stdin (channel 0) from the keyboard to a file. wc reads a nameless stream.", "nodes": [ { "id": "file", "label": "fruits.txt", "kind": "file", "col": 0, "row": 0 }, { "id": "cmd", "label": "wc -l", "kind": "command", "col": 2, "row": 0 }, { "id": "screen", "label": "screen", "kind": "screen", "col": 4, "row": 0 } ], "edges": [ { "from": "file", "to": "cmd", "label": "< stdin (0)", "kind": "stdin", "stage": 1 }, { "from": "cmd", "to": "screen", "label": "stdout (1)", "kind": "stdout", "stage": 2 } ] }

Before you run it, decide: will the output be exactly 5 fruits.txt again, or something different?

wc -l < fruits.txt

prompt: student@linuxcamp:~/signal$ answer: wc -l < fruits.txt output: 5 hint: wc -l, then the < operator, then the file to feed in: wc -l < fruits.txt

Just 5. The filename is gone, and that is the aha of this lesson. This time wc never opened a file. The shell opened fruits.txt, poured it into channel 0, and wc read a nameless stream of text. It counted five lines, but it has no idea where they came from, so it has no name to print.

If the vanishing filename made sense, you already own the hard part of this lesson. Everything after this point is repetition on a new command.

Hold on to the rule: with <, the command reads a stream, not a file. It cannot tell a redirected file from live typing. That is why the stdin form prints the bare 5, which is exactly what a script wants when it needs a clean number with no filename to trim off. And any command that reads standard input will accept <: sort, grep, tr, and dozens more you will meet in later lessons.

sort reads lines and prints them in order; its full lesson comes in the Text Processing section. It happily reads from stdin, which makes it a perfect second test for <.

First, look at the raw file so you know what unsorted looks like:

cat colors.txt

prompt: student@linuxcamp:~/signal$ answer: cat colors.txt output: red green green blue hint: cat, a space, then the filename: cat colors.txt

Four colors, out of order, with green in there twice. Now feed the file into sort through channel 0. Before you run it, decide: which color will print first?

sort < colors.txt

prompt: student@linuxcamp:~/signal$ answer: sort < colors.txt output: blue green green red hint: sort, then the < operator, then the file: sort < colors.txt

blue rose to the top: alphabetical order. sort read the four colors from channel 0 without ever learning the name colors.txt, sorted them, and printed the result. Notice the doubled green survived; sort orders lines, it does not remove repeats. The pattern is the same as with wc: the command did its job on a nameless stream the shell fed it.

No commands are shown from here on. You have every piece you need: one operator and two commands you have already driven.

Challenge 1. Count the lines of fruits.txt so that only the number prints, no filename. That means wc must never learn the file's name.

prompt: student@linuxcamp:~/signal$ answer: wc -l < fruits.txt output: 5 hint: The shell must open the file, so feed it in with the < operator: wc -l < fruits.txt

Challenge 2. Print the colors of colors.txt in alphabetical order by feeding the file into sort through stdin.

prompt: student@linuxcamp:~/signal$ answer: sort < colors.txt output: blue green green red hint: Feed the file into sort with the < operator: sort < colors.txt

Challenge 3. Now the mirror image: count the lines of fruits.txt so the filename shows up next to the count. Pick the form where wc opens the file itself.

prompt: student@linuxcamp:~/signal$ answer: wc -l fruits.txt output: 5 fruits.txt hint: No redirect this time; hand the filename to wc as an argument: wc -l fruits.txt

Three for three, from memory. You chose the stdin form when the name had to vanish, and the argument form when the name had to show. That choice, who opens the file, is exactly what the < operator controls.

You earned this cheat sheet. Every row is a form you have already run on the signal files:

The one rule to carry away: < points channel 0 at a file. The command then reads the file's contents as a nameless stream, exactly as if you had typed them. > and >> steer output; < steers input. They are mirror images: > empties channel 1 into a file, < fills channel 0 from one.

Mind the direction of the arrow. < reads from the file and never changes it. > writes to the file and wipes it first. Typing wc -l > fruits.txt by mistake would empty your data file before wc even ran. Picture the bracket as an arrowhead showing which way the data flows.

You fed files into commands through stdin and watched the output prove it: the bare 5 from wc, the sorted colors from sort, and the argument form beside them for contrast. Every one of those you typed yourself and saw the real result.

The Redirection module ends with one real Linux machine: the redirection mission lab. There a VM boots just for you with this same signal folder built, fruits.txt and colors.txt and the rest in place. The mission hands you objectives that use exactly what you just ran, and it shows no commands. You read the objective, recall the operator, and type it. That recall is what makes it stick.

Finish the other Redirection lessons, then go run the signal for real.

Practice Input Redirection in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.