← 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.

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
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.