Linux online course

Linux Streams: Standard Input, Output, and Error

Learn how Linux stdin, stdout, and stderr work, including file descriptors, redirection, pipelines, /dev/null, and troubleshooting mixed output.

Linux commands communicate through streams: ordered flows of data entering or leaving a running program. A command runs as a process. It can read data from an input stream and write data to one or more output streams.

An input stream supplies data to a program. Output streams carry data away from it. The keyboard and terminal are common defaults, but they are not the only possible sources or destinations. A file, another command, or a special device can also provide or receive stream data.

The Three Standard Streams

Command-line programs conventionally start with three standard streams:

StreamAbbreviationFile descriptorTypical default source or destinationPrimary use
Standard inputstdin0Keyboard or terminalData read by a command
Standard outputstdout1Terminal displayNormal command results
Standard errorstderr2Terminal displayDiagnostics and error messages

A file descriptor is a small integer that a process uses as a handle for an open input/output resource. The shell and the process use descriptors 0, 1, and 2 to refer to stdin, stdout, and stderr.

Default Stream Connections

In a typical interactive terminal, the flow looks like this:

keyboard or terminal input ──> stdin (0) ──> command/process ──> stdout (1) ──> terminal
                                                   └──> stderr (2) ──> terminal

Both stdout and stderr normally appear on the same terminal, but they remain separate streams. The shell establishes these connections before launching a command, and shell syntax can change them.

Keeping stdout and stderr separate is useful when normal results must be saved, processed, or piped while diagnostics remain visible or go to a different file.

Standard Input

Standard input, or stdin, is the normal data source read by a command. During an interactive session, it usually receives characters typed at the keyboard.

Some commands read stdin when no input file is named. For example, cat copies stdin to stdout:

cat

Type one or more lines. Each line is copied to the terminal. On many terminals, press Ctrl+D to indicate end-of-input.

Stdin can also come from a file, a here-document, a here-string, or another command.

Input Redirection from a File

The < operator makes a file become stdin:

sort < names.txt

The shell opens names.txt and supplies it to sort. The command behaves as though the data arrived through standard input rather than from the keyboard.

Other Input Sources

A pipeline supplies stdin from another command:

printf '%s\n' banana apple cherry | sort

A here-document provides a block of text as stdin:

cat <<EOF
First line
Second line
EOF

A here-string provides one string as stdin:

wc -w <<< 'Linux streams are useful'

Standard Output

Standard output, or stdout, is the normal channel for a command's results. Unless redirected, stdout is displayed in the terminal.

echo "Hello, Linux"

This command writes its normal result to stdout, so the terminal displays it.

Writing stdout to a File

The > operator redirects stdout to a file and replaces that file's existing contents:

ls > files.txt

To append stdout to the end of a file instead, use >>:

date >> activity.log

You can explicitly identify stdout with file descriptor 1:

ls 1> files.txt

For ordinary output, > and 1> have the same effect.

Standard Error

Standard error, or stderr, is intended for diagnostics, warnings, and error messages. It uses file descriptor 2.

For example, this command may produce normal results for /etc and an error for /missing:

find /etc /missing

The normal results go to stdout, while the diagnostic goes to stderr. Both commonly appear on the terminal, which can make them look like one output stream even though they are separate.

Redirecting stderr

Use 2> to write stderr to a file, replacing that file's contents. Use 2>> to append diagnostics:

find /etc /missing 2> errors.txt
command 2>> errors.log

To keep normal output and errors separate, redirect each descriptor independently:

find /etc /missing > results.txt 2> errors.txt

Here, successful results go to results.txt, while diagnostics go to errors.txt.

Combining stdout and stderr

The operator 2>&1 sends stderr to the current destination of stdout. A common form is:

command > all.txt 2>&1

The order matters. First, > all.txt sends stdout to all.txt. Then 2>&1 sends stderr to the same destination. This is the reliable form for putting both streams in one file.

Redirection is evaluated from left to right. For example:

command 2>&1 > all.txt

In this order, stderr first copies the original stdout destination, usually the terminal. The later stdout redirection does not change stderr's already-established destination, so the two streams may not both enter all.txt.

Discarding Output with /dev/null

/dev/null is a special device that accepts written data and discards it. Use it when a particular stream is intentionally unneeded:

find /etc /missing 2> /dev/null

This suppresses diagnostics while leaving normal stdout visible. To discard normal output, use > /dev/null. To discard both streams, use:

command > /dev/null 2>&1

Redirection Fundamentals

SyntaxEffectExample
< fileUse a file as stdinsort < names.txt
> fileWrite stdout to a file, replacing its contentsls > files.txt
>> fileAppend stdout to a filedate >> activity.log
2> fileWrite stderr to a file, replacing its contentscommand 2> errors.txt
2>> fileAppend stderr to a filecommand 2>> errors.log
2>&1Send stderr to the current stdout destinationcommand > all.txt 2>&1
|Send stdout to the next command's stdincommand | less

Pipelines

A pipeline connects commands. The pipe operator | sends the first command's stdout to the second command's stdin.

ls -1 | wc -l

Here, ls -1 writes one entry per line to stdout. The pipe supplies that data as stdin to wc -l, which counts the lines.

Pipelines are useful for filtering, searching, counting, and transforming output:

printf '%s\n' apple banana apricot | grep '^ap' | wc -l

A basic pipe transfers stdout only. Stderr remains connected to its existing destination, usually the terminal. Therefore, this does not normally send error messages to grep:

find /etc /missing | grep denied

To include stderr, merge it into stdout before the pipe:

find /etc /missing 2>&1 | grep -i "denied"

Reading Mixed Output

Normal results and diagnostics can appear interleaved on a terminal because both streams share the same visible destination. Their order may also seem unexpected because programs can buffer stdout and stderr differently or write to them at different times.

When investigating a command, capture the streams separately:

find /etc /missing > results.txt 2> errors.txt

Then inspect each file independently:

less results.txt
less errors.txt

When scripting, do not assume every command uses stdout and stderr in exactly the same way. Consult the command's documentation when deciding which stream should be captured, displayed, or piped.

Troubleshooting Stream Problems

Errors Still Appear on the Screen

If you run command > output.txt and errors still appear, only stdout was redirected. Stderr is still connected to the terminal. Use command 2> errors.txt or combine both streams with command > output.txt 2>&1.

A Pipeline Does Not Process Errors

A normal pipe transfers stdout only. If grep or wc does not receive error messages, merge stderr before the pipe:

command 2>&1 | grep pattern

Earlier File Contents Disappeared

The > operator overwrites a destination file. Use >> when new output should be appended instead.

A Command Waits for Input

A command may appear to pause because it is reading stdin. Type the required input, redirect a file with <, pipe data into it, or send end-of-input when appropriate.

Combined Output Has Unexpected Ordering

Even after combining streams, output order can be affected by buffering and by the times at which the program writes each stream. Capture stdout and stderr separately when precise diagnosis or ordering matters.

Quick Reference

  • stdin (0): data read by a command.
  • stdout (1): normal command results.
  • stderr (2): diagnostics, warnings, and errors.
  • Redirection: shell syntax that changes a stream's source or destination.
  • Pipeline: a connection from one command's stdout to another command's stdin.
  • <: read stdin from a file.
  • >: overwrite a file with stdout.
  • >>: append stdout to a file.
  • 2>: overwrite a file with stderr.
  • 2>&1: send stderr to stdout's current destination.
  • /dev/null: discard written data.

For related fundamentals, see Bourne Again Shell Bash, Search For Text Strings Using Grep, File Structure In Linux, and Linux command-line topics.