← Back to Bash Course | Chapter 8: Input/Output & Redirection | Lesson 4 of 13

stdin, stdout, stderr and File Descriptors

Every running program has three default pipes for text: one to read input from, and two to send output to, and Bash calls them by the numbers 0, 1, and 2.
Syntax
bash
command 1> file      # stdout (fd 1)
command 2> file      # stderr (fd 2)
command < file       # stdin (fd 0)
echo "message" >&2

The Three Standard Streams

Every process starts with three open file descriptors: 0 (stdin, input), 1 (stdout, normal output), and 2 (stderr, error output). Bash lets you target any of them explicitly using the N> syntax.

Example: The Three Standard Streams

bash
#!/bin/bash
echo "this goes to stdout" 1>&1
echo "this goes to stderr" 1>&2

Sending Error Messages to stderr

Well-behaved scripts print diagnostics and errors to stderr with >&2 so that normal output on stdout stays clean and can be piped or captured separately.

Note: Use a small log_error helper like this instead of scattering >&2 everywhere.

Example: Sending Error Messages to stderr

bash
#!/bin/bash
log_error() {
    echo "ERROR: $1" >&2
}

log_error "something went wrong"
echo "normal output continues on stdout"

Order Matters When Merging Streams

cmd > file 2>&1 first points stdout at file, then makes stderr a copy of the (now redirected) stdout, so both land in file.

Reversing the order to cmd 2>&1 > file makes stderr a copy of the *old* stdout (the terminal) before stdout moves to the file.

Warning: Read redirections left to right; 2>&1 > file is a very common bug because it does not do what people expect.

Example: Order Matters When Merging Streams

bash
#!/bin/bash
{ echo "out line"; echo "err line" >&2; } > both.log 2>&1
echo "--- both.log contents ---"
cat both.log
rm -f both.log

Checking Which Stream a Descriptor Points To

The test -t operator (or [ -t N ]) tells you whether file descriptor N is connected to a terminal. In a non-interactive script it usually is not, which is useful for deciding whether to print colored output.

Example: Checking Which Stream a Descriptor Points To

bash
#!/bin/bash
if [ -t 1 ]; then
    echo "stdout is a terminal"
else
    echo "stdout is redirected or non-interactive"
fi
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Thinking error messages printed with echo automatically go to stderr; plain echo always writes to stdout (fd 1) unless redirected.
  2. Confusing the order of 2>&1 placement; cmd > file 2>&1 and cmd 2>&1 > file behave differently because redirections are applied left to right.
  3. Assuming file descriptor numbers are fixed forever in a script; they can be closed, duplicated, and reopened at any point.
Chapter Summary
  • File descriptor 0 is stdin, 1 is stdout, 2 is stderr.
  • echo and printf write to stdout by default; only explicit redirection sends text to stderr.
  • >&2 after a command redirects that command's stdout into stderr.
  • Redirections are processed left to right, so order matters when combining them.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.