thelinuxvault blog

Introduction to Bash Shell Redirections

The Bash shell is a powerful tool for interacting with Unix-like operating systems, enabling users to execute commands, automate tasks, and manage system resources. One of its most essential features is redirection, which allows you to control where input comes from and where output (including errors) is sent. Whether you’re a beginner learning the command line or an experienced developer writing scripts, mastering redirection will significantly enhance your efficiency and flexibility.

In this guide, we’ll demystify Bash redirections, starting with foundational concepts like file descriptors and standard streams, then diving into practical examples of input/output redirection, error handling, and advanced techniques. By the end, you’ll be able to redirect output to files, capture errors, feed input to commands from files or inline text, and even combine outputs from multiple commands.

2026-02

Table of Contents#

  1. Understanding File Descriptors
  2. Standard Streams: stdin, stdout, stderr
  3. Output Redirection
  4. Input Redirection
  5. Redirecting Standard Error (stderr)
  6. Redirecting Both stdout and stderr
  7. Here Documents (<<) and Here Strings (<<<)
  8. Process Substitution
  9. Advanced Redirection Tips
  10. Conclusion
  11. References

1. Understanding File Descriptors#

Before diving into redirection, we need to understand file descriptors (FDs). A file descriptor is a non-negative integer that the operating system uses to track open files and streams. When a process starts, it inherits three standard file descriptors from its parent (usually the shell):

File DescriptorNamePurposeDefault Source/Destination
0stdinStandard InputKeyboard
1stdoutStandard OutputTerminal (screen)
2stderrStandard ErrorTerminal (screen)

Redirection lets you change the source (for input) or destination (for output) of these file descriptors.

2. Standard Streams: stdin, stdout, stderr#

By default:

  • stdin (0): The input stream for commands. Most commands read input from stdin if no file is specified (e.g., read, grep without a filename).
  • stdout (1): The output stream for successful command results (e.g., ls listing files, echo "Hello").
  • stderr (2): The output stream for error messages (e.g., ls non_existent_file prints "No such file or directory" to stderr).

Separating stdout and stderr ensures errors don’t get mixed with regular output, which is critical for scripting and logging.

3. Output Redirection#

Output redirection sends stdout (or stderr) to a file instead of the terminal. The most common operators are > (overwrite) and >> (append).

3.1 Overwriting Output with >#

The > operator redirects stdout to a file, overwriting the file if it exists. If the file doesn’t exist, it’s created.

Syntax:

command > filename  

Examples:

  • Save a directory listing to files.txt:

    ls -l > files.txt  

    If files.txt existed, its old content is replaced with the output of ls -l.

  • Save the output of echo to a file:

    echo "Hello, World!" > greeting.txt  

3.2 Appending Output with >>#

The >> operator appends stdout to a file, preserving existing content.

Syntax:

command >> filename  

Examples:

  • Add a new line to greeting.txt without overwriting:

    echo "Goodbye, World!" >> greeting.txt  

    Now greeting.txt contains:

    Hello, World!  
    Goodbye, World!  
    
  • Append logs to a file:

    date >> activity.log  # Adds current date/time to activity.log  

4. Input Redirection#

Input redirection sends data from a file to a command’s stdin, replacing the default keyboard input. Use the < operator.

Syntax:

command < filename  

Examples:

  • Read input from greeting.txt using cat (though cat filename is more common, this demonstrates redirection):

    cat < greeting.txt  
  • Count lines in a file with wc -l (word count, lines):

    wc -l < data.txt  # Output: number of lines in data.txt  
  • Use grep to search for a pattern in a file (equivalent to grep "pattern" filename):

    grep "error" < app.log  

5. Redirecting Standard Error (stderr)#

By default, stderr (FD 2) prints to the terminal. To redirect errors to a file, explicitly target FD 2 with 2>.

Overwriting Errors with 2>#

Syntax:

command 2> error_filename  

Example:

  • Capture errors from a failed command (e.g., listing a non-existent file):
    ls non_existent_file 2> errors.log  
    The error message ls: cannot access 'non_existent_file': No such file or directory is saved to errors.log instead of printing to the terminal.

Appending Errors with 2>>#

To append errors to a file (instead of overwriting), use 2>>:

command 2>> error_filename  

Example:

  • Append errors from multiple commands to errors.log:
    ls file1 2>> errors.log  
    ls file2 2>> errors.log  # Both errors go to errors.log (no overwrites)  

6. Redirecting Both stdout and stderr#

Often, you’ll want to capture both regular output (stdout) and errors (stderr) in the same file. Two common methods exist:

6.1 Using &> (Bash Shortcut)#

Bash provides the &> operator as a shortcut to redirect both stdout and stderr to a file.

Syntax:

command &> combined_output.log  

Example:

  • Capture all output (success and errors) from a script:
    ./my_script.sh &> script_output.log  

6.2 Using 2>&1 (Portable Syntax)#

The 2>&1 syntax redirects stderr (FD 2) to the same destination as stdout (FD 1). This works in all POSIX-compliant shells (not just Bash), making it more portable.

Syntax:

command > combined_output.log 2>&1  

Example:

  • Redirect stdout to output.log, then redirect stderr to stdout (so both go to output.log):
    curl https://example.com > output.log 2>&1  

⚠️ Note: The order matters! 2>&1 must come after the stdout redirection (>). If you write command 2>&1 > output.log, stderr will redirect to the original stdout (terminal), and only stdout will go to the file.

7. Here Documents (<<) and Here Strings (<<<)#

These features let you provide input to a command inline (directly in the shell or script) instead of from a file.

7.1 Here Documents (<<)#

A here document (heredoc) passes a block of text as stdin to a command. Use << DELIMITER to start the block, and DELIMITER (on a new line) to end it.

Syntax:

command << DELIMITER  
line 1  
line 2  
...  
DELIMITER  

Examples:

  • Use cat to create a file with multi-line content:

    cat << EOF > poem.txt  
    Roses are red,  
    Violets are blue,  
    Bash is fun,  
    And so are you!  
    EOF  

    This creates poem.txt with the four lines above.

  • Run a mysql command with inline SQL:

    mysql -u user -p << SQL  
    SELECT * FROM users;  
    exit;  
    SQL  
  • Ignore leading tabs with - (useful for indentation in scripts):

    cat <<- EOF > indented.txt  
      This line has leading tabs,  
      but they'll be ignored!  
    EOF  

7.2 Here Strings (<<<)#

A here string is a shorter alternative to heredocs for single-line input. Use <<< "string" to pass a string as stdin.

Syntax:

command <<< "input_string"  

Examples:

  • Use grep to search a string directly:

    grep "blue" <<< "Roses are red, Violets are blue"  # Output: Violets are blue  
  • Count characters in a string with wc -c:

    wc -c <<< "Hello"  # Output: 6 (includes newline character)  

8. Process Substitution#

Process substitution treats the output of a command as a temporary file, allowing you to pass it to another command that expects a file argument. Use <(command) for input (stdout of command as a file) or >(command) for output (write to command as a file).

Syntax:

# Input: Use <(command) as a "file" for another command  
command1 <(command2)  
 
# Output: Write to >(command) as a "file"  
command1 >(command2)  

Examples:

  • Compare the output of two ls commands with diff:

    diff <(ls dir1) <(ls dir2)  # Shows differences between listings of dir1 and dir2  
  • Grep a log file and save matches to a file and print to the terminal (using tee):

    grep "error" <(tail -f app.log) >(tee errors.log)  

    Here, <(tail -f app.log) streams the end of app.log, and >(tee errors.log) writes matches to errors.log and stdout.

9. Advanced Redirection Tips#

9.1 Discarding Output with /dev/null#

The special file /dev/null discards all input written to it (often called the "bit bucket"). Use it to suppress unwanted output.

Examples:

  • Discard stdout (keep stderr):

    command > /dev/null  # Errors still print to terminal  
  • Discard stderr (keep stdout):

    command 2> /dev/null  # Output prints to terminal; errors are hidden  
  • Discard both stdout and stderr:

    command > /dev/null 2>&1  # No output at all  

9.2 Redirecting All Output in a Script#

To redirect all stdout and stderr for an entire script, use exec at the top. exec replaces the current shell process, so redirections set with exec persist for the script’s duration.

Example:

#!/bin/bash  
# Redirect all output to script.log  
exec > script.log 2>&1  
 
echo "This goes to script.log"  
ls non_existent_file  # Error also goes to script.log  

10. Conclusion#

Bash redirection is a cornerstone of command-line mastery, enabling you to control input/output flows, automate tasks, and debug scripts effectively. From simple file redirection with > and < to advanced techniques like process substitution and heredocs, these tools empower you to handle data flexibly in the shell.

Practice with real-world scenarios—like logging script output, capturing errors, or combining command outputs—to solidify your understanding. With redirection in your toolkit, you’ll write more robust scripts and work more efficiently on the command line.

11. References#