Understanding stdin, stdout, and stderr

Understanding stdin, stdout, and stderr

What Are the Standard Streams?

Saving a log with > file, chaining commands with a | (pipe) — as you learn the command line, you keep running into these symbols. Behind them is a mechanism called the standard streams: stdin, stdout, and stderr.

This guide untangles what each of the three streams is, why output is split into two kinds, and how to switch where input and output go using redirection and pipes — all through a conversation between Lina and Linny-senpai.

What You'll Learn

  • What stdin, stdout, and stderr are each responsible for
  • Why output is split into two streams (stdout and stderr)
  • The meaning of the numbers 0 / 1 / 2 (file descriptors)
  • How to switch destinations with >, 2>, and &>
  • How to use the pipe | and input redirection <

1. What Are the Standard Streams?

Conclusion: The standard streams are three default paths a command uses — one to take input, one to send normal results, and one to send errors. They are called stdin, stdout, and stderr.

Lina: Linny-senpai, I saw the term "standard streams," and it sounds intimidating...
Linny-senpai: The name is fancy, but the idea is simple. Every command has a way for data to come in and a way for results to go out. There are three default paths for that, and each has a name.
Lina: Three of them?
Linny-senpai: Right. Here's how they break down.
  • stdin (standard input): the entrance where data comes into the command
  • stdout (standard output): the exit for normal results
  • stderr (standard error): the exit for errors and warnings
Lina: So one entrance and two exits.
Linny-senpai: Exactly. You may not notice them, but every command always runs with these three channels open.

What "standard" means

"Standard" means "the default path used unless you say otherwise." For example, the result of ls appears on screen because stdout's default destination is the screen (the terminal). Redirection and pipes are simply ways to change that destination afterward.

2. Why Is Output Split Into stdout and stderr?

Conclusion: To keep "results you want to pass on" separate from "errors you want a human to read." Splitting them lets you save just the results or grab just the errors.

Lina: But why are there two exits? Wouldn't one be simpler?
Linny-senpai: Good question. Picture this: you process many files and want to save the results to a file. If the results and the error messages came out of the same exit, the error text would get mixed into your saved file.
Lina: Oh... right. I just want the clean results, but garbage gets mixed in.
Linny-senpai: Exactly. So Linux separates them from the start:
  • stdout = normal results (data you want to pass on or save)
  • stderr = errors and warnings (messages meant for a human)

That way, even if you save the results to a file, the errors still show up on screen so you don't miss them.

Lina: I see! The exits are split by role.

A familiar analogy

On a factory line, stdout is the "conveyor belt carrying finished products," and stderr is the "alarm that signals a defect." You don't want the alarm sound inside the box of finished goods (the file). So they're kept separate.

3. What Are the Numbers 0 / 1 / 2?

Conclusion: stdin, stdout, and stderr are assigned the numbers 0 / 1 / 2 (file descriptors). The 2 in 2> refers to that number.

Lina: I saw the notation 2> in an example — what is that 2?
Linny-senpai: That's the number for stderr. Each of the three standard streams has an integer assigned to it, like a jersey number.
Lina: A jersey number...?
Linny-senpai: It's called a "file descriptor" — a number a command uses to tell its channels apart. You only need to remember three.
Number Name Role
0 stdin Standard input (entrance)
1 stdout Standard output (normal exit)
2 stderr Standard error (error exit)

How numbers map to symbols

The redirection symbols connect directly to these numbers.

  • > is shorthand for 1> (sends stdout)
  • 2> sends stderr
  • < is shorthand for 0< (reads stdin)

Once you remember "the 2 in 2> is stderr's number," the symbols suddenly make sense.

4. How Do I Change Where Output Goes?

Conclusion: Use > to send stdout and 2> to send stderr to a file. To combine both, use > file 2>&1 or &> file.

Lina: I understand the exits are separate. So how do I save just the results to a file?
Linny-senpai: You use "redirection" — the act of re-routing an exit from the screen to a file. Let's start by saving stdout to a file.
ls /etc > filelist.txt

With >, the stdout content that would have appeared on screen is written to filelist.txt instead (nothing appears on screen). Note that > overwrites, while >> appends.

To save only the errors, use 2>.

ls /not-exist 2> errors.txt
(nothing appears on screen; errors.txt records the following)
ls: cannot access '/not-exist': No such file or directory
Lina: So stdout is > and stderr is 2>. What if I want both in one file?
Linny-senpai: Then you add 2>&1. It means "send stderr (2) to the same destination as stdout (1)."
command > output.txt 2>&1

Order matters with 2>&1

2>&1 means "make stderr match stdout's current destination." So you must write > output.txt first. If you reverse the order, like command 2>&1 > output.txt, stderr stays pointed at its old destination (the screen). The newer &> file notation (bash) combines both without worrying about order.

command &> output.txt

5. How Do Pipes and Standard Input Work?

Conclusion: A pipe | connects the left command's stdout to the right command's stdin. < feeds a file's contents in as stdin.

Lina: When do I actually use stdin (the entrance)? I've never really thought about it...
Linny-senpai: You use it every time you pipe, behind the scenes. A pipe | connects the left command's stdout directly to the right command's stdin.
ls /etc | grep conf

In this example, the output (stdout) of ls /etc flows straight into the input (stdin) of grep conf. grep then picks out only the lines that contain conf.

Picture the flow

ls /etc  ──stdout──▶  |  ──stdin──▶  grep conf  ──stdout──▶  screen

A pipe is like a hose that connects "the previous command's exit" directly to "the next command's entrance."

To feed a file's contents in as stdin, use <.

sort < names.txt

This streams the contents of names.txt into the standard input of sort, which sorts and prints them. The result is the same as sort names.txt, but it makes the "connect a file to stdin" behavior of standard input easy to see.

To practice pipes and redirection more hands-on, see Pipes and Redirection Basics. When you want output to go to both the screen and a file, How to Use the tee Command is handy.

Summary

  • The standard streams are three paths: stdin (input), stdout (normal output), and stderr (error output)
  • There are two output streams to keep "results" and "errors" from mixing
  • The three are assigned the numbers 0 / 1 / 2 (file descriptors)
  • Use > for stdout and 2> for stderr to send them to a file (both with > file 2>&1 or &> file)
  • A pipe | connects stdout to the next stdin, and < feeds a file in as stdin

Next Reading