File Descriptor

Shell Process File Descriptors SHELL PROCESS FD 0: stdin FD 1: stdout FD 2: stderr Keyboard (Terminal) File < input.txt Pipe cmd1 | cmd2 Terminal Display File > output.txt Next Cmd cmd1 | cmd2 Terminal (Errors) Error File 2> errors.txt /dev/null 2> /dev/null FD 0 FD 1 FD 2 Common Redirection Examples: echo "hello" > file.txt # stdout to file ls /bad 2> errors.txt # stderr to file sort < input.txt # stdin from file cmd 2> /dev/null # discard errors File Descriptor Numbers: 0 = stdin (input) 1 = stdout (normal output) 2 = stderr (error output) Always available in every process

File Descriptors - Fundamentals

What are File Descriptors?

File descriptors are non-negative integers that represent open files or input/output channels in Unix-like systems. Every process starts with three standard file descriptors:

  • 0 = stdin (standard input)
  • 1 = stdout (standard output)
  • 2 = stderr (standard error)

Basic Redirection

# Redirect stdout to a file
echo "Hello" > output.txt        # Same as: echo "Hello" 1> output.txt

# Redirect stdin from a file
cat < input.txt                  # Same as: cat 0< input.txt

# Redirect stderr to a file
ls /nonexistent 2> errors.txt

# Append to a file instead of overwriting
echo "More text" >> output.txt

Testing File Descriptors

Use the -t test to check if a file descriptor is connected to a terminal:

# Check if stdout is a terminal
if [ -t 1 ]; then
    echo "Output is going to terminal"
else
    echo "Output is redirected/piped"
fi

# Check stdin
[ -t 0 ] && echo "Input is from terminal"

# Check stderr
[ -t 2 ] && echo "Errors go to terminal"

More on this in Detecting Output Destination in CLI Programs

File Descriptors - Intermediate

Combining and Duplicating Streams

The & Notation

The & in redirections means "file descriptor":

# Redirect stderr to wherever stdout is going
command 2>&1

# Shorthand: redirect both stdout and stderr to file
command &> output.txt    # Same as: command > output.txt 2>&1
command &>> output.txt   # Append version

Order Matters!

# WRONG: stderr still goes to terminal
command > file.txt 2>&1  # Correct order

command 2>&1 > file.txt  # WRONG: stderr goes to original stdout

Common Patterns

Silencing Output

# Discard all output
command > /dev/null 2>&1

# Discard only errors
command 2> /dev/null

# Discard output but keep errors
command > /dev/null

Logging Patterns

#!/bin/bash
# log-wrapper.sh - Log all output while still displaying it

# Log both stdout and stderr to file while showing on screen
./mycommand 2>&1 | tee output.log

# Separate error logging
./mycommand 2> >(tee -a error.log >&2) | tee -a output.log

Conditional Output

# verbose.sh - Control output verbosity
VERBOSE=${VERBOSE:-0}

debug() {
    [ "$VERBOSE" -eq 1 ] && echo "[DEBUG] $*" >&2
}

info() {
    echo "[INFO] $*"
}

error() {
    echo "[ERROR] $*" >&2
}

# Usage
debug "This only shows if VERBOSE=1"
info "This always shows"
error "This goes to stderr"

Reading and Writing Simultaneously

# Process a file in-place (careful!)
while IFS= read -r line; do
    echo "PROCESSED: $line"
done < input.txt > temp.txt && mv temp.txt input.txt

Advanced


Children
  1. Advanced
  2. File Descriptor Image
  3. Fundumentals
  4. Intermediate

Backlinks