How to Redirect Output in Linux Commands

Linux output redirection sends a command’s output somewhere other than the terminal screen. Use > to redirect stdout to a file (overwriting it): ls -la > filelist.txt. Use >> to append instead of overwrite: echo "new line" >> file.txt. Use 2> to redirect only error messages: command 2> errors.log. Use &> or 2>&1 to redirect both stdout and stderr together. Use < to redirect a file’s contents as input to a command: sort < names.txt.

Controlling Where Output Goes

Every command you run in a Linux terminal produces output — and by default, that output appears on your screen. But “the screen” is not actually where output goes technically; it is simply the default destination the shell connects each command to when nothing else is specified. Understanding this distinction, and knowing how to redirect output to files, other commands, or nowhere at all, is one of the most practically important skills for working effectively at the Linux command line.

Redirection lets you save command output for later review, separate normal output from error messages, feed one program’s output into another as input, silence noisy commands, and build scripts that log their activity automatically. Every system administrator, every shell script, and every automated task on Linux relies extensively on redirection to control exactly where information flows.

This article explains the standard streams that make redirection possible, covers every redirection operator with practical examples, and demonstrates the patterns you will use constantly once you understand them.

The Three Standard Streams

Every process in Linux has three standard communication channels, established when the process starts:

Standard Input (stdin, file descriptor 0) — where the program reads input from. By default, connected to your keyboard.

Standard Output (stdout, file descriptor 1) — where the program writes its normal output. By default, connected to your terminal screen.

Standard Error (stderr, file descriptor 2) — where the program writes error messages and diagnostics. By default, also connected to your terminal screen.

The critical insight: stdout and stderr are separate streams, even though both appear on your screen by default and look identical to you. This separation is what makes it possible to redirect normal output and error messages independently — capturing one while letting the other display normally, or vice versa.

Seeing the Separation

$ ls /home/sarah /nonexistent
ls: cannot access '/nonexistent': No such file or directory
/home/sarah:
Desktop  Documents  Downloads

The successful listing (/home/sarah: and its contents) went to stdout. The error message (ls: cannot access...) went to stderr. Both appeared on screen, but they are fundamentally different streams that can be redirected independently.

Redirecting Standard Output: >

The > operator redirects a command’s stdout to a file, overwriting the file’s existing content (or creating the file if it does not exist):

$ ls -la > filelist.txt
$ cat filelist.txt
total 24
drwxr-xr-x  5 sarah sarah 4096 Feb 18 09:22 .
drwxr-xr-x 25 sarah sarah 4096 Feb 17 20:15 ..
-rw-r--r--  1 sarah sarah 8192 Feb 16 11:34 report.pdf

Nothing appears on screen when you run this — the entire output went into filelist.txt instead.

Overwriting Behavior: The Critical Warning

Each time you run a command with > to the same file, the file’s previous contents are completely replaced:

$ echo "First line" > notes.txt
$ cat notes.txt
First line

$ echo "Second line" > notes.txt
$ cat notes.txt
Second line

Notice “First line” is gone entirely — > does not append, it replaces. This is one of the most common sources of accidental data loss for new Linux users. Always be certain before using > against a file that might contain content you want to keep.

Appending Instead of Overwriting: >>

The >> operator appends to a file’s existing content rather than replacing it:

$ echo "First line" > notes.txt
$ echo "Second line" >> notes.txt
$ echo "Third line" >> notes.txt
$ cat notes.txt
First line
Second line
Third line

If the file does not exist yet, >> creates it (behaving like > in that specific case). The difference only matters when the target file already has content you want to preserve.

Rule of thumb: use > when you want a fresh file each time (like a log file for a single run), and >> when you want to accumulate content across multiple runs (like an ongoing log file that should retain history).

Redirecting Standard Error: 2>

The 2> operator redirects only stderr, leaving stdout to display normally on screen:

$ ls /home/sarah /nonexistent 2> errors.log
/home/sarah:
Desktop  Documents  Downloads

$ cat errors.log
ls: cannot access '/nonexistent': No such file or directory

The successful part of the output (/home/sarah: listing) still appeared on screen because only stderr (file descriptor 2) was redirected. The error message was captured silently into errors.log.

Appending Error Output

$ command 2>> errors.log

Just as >> appends stdout, 2>> appends stderr — useful for accumulating error logs across multiple script runs.

Discarding Error Messages Entirely

Redirect stderr to /dev/null — a special device file that discards anything written to it:

$ find / -name "*.conf" 2> /dev/null

This is extremely common when running commands (like find searching system-wide) that generate many “Permission denied” errors you do not care about — the errors vanish silently while the useful output (successful matches) still displays.

Redirecting Both stdout and stderr Together

The Modern Shorthand: &>

$ command &> combined_output.log

This redirects both stdout and stderr into the same file. Everything the command produces — normal output and error messages alike — ends up in combined_output.log, with nothing displayed on screen.

Appending both streams:

$ command &>> combined_output.log

The Traditional Method: 2>&1

Before &> was widely supported, the standard way to combine streams was:

$ command > combined_output.log 2>&1

This reads as: “redirect stdout to combined_output.log, then redirect stderr to wherever stdout is now going (file descriptor 1).”

Order matters critically here:

$ command 2>&1 > combined_output.log     # WRONG order
$ command > combined_output.log 2>&1     # CORRECT order

In the wrong-order version, 2>&1 executes first, redirecting stderr to wherever stdout currently points — which at that moment is still the terminal screen. Then > combined_output.log redirects stdout to the file. The result: stdout goes to the file, but stderr still goes to the screen — not what was intended.

The correct order redirects stdout to the file first, establishing the new destination, and then points stderr at that same destination.

Both &> and > file 2>&1 accomplish the same result — &> is simply a more concise, modern shorthand that avoids the ordering pitfall entirely. Both are widely used; &> is Bash-specific while 2>&1 works in virtually any POSIX shell, which is why it appears more often in portable scripts.

Sending Output Nowhere: /dev/null

/dev/null is a special file that discards everything written to it and returns end-of-file immediately when read. It is the standard way to silence output you do not want to see or keep.

$ noisy_command > /dev/null              # Discard only stdout
$ noisy_command 2> /dev/null             # Discard only stderr
$ noisy_command > /dev/null 2>&1         # Discard everything
$ noisy_command &> /dev/null             # Discard everything (shorthand)

Common Use Cases for /dev/null

Silencing a command entirely in a script:

if ping -c 1 google.com &> /dev/null; then
    echo "Internet is up"
else
    echo "Internet is down"
fi

Here, we do not care about ping’s actual output — only whether it succeeded (checked via its exit code). Discarding all output keeps the script’s own output clean.

Suppressing expected errors:

mkdir /tmp/mydir 2> /dev/null    # Don't complain if it already exists

Reading from /dev/null (produces empty input):

$ command < /dev/null    # Provide empty input instead of waiting for keyboard input

This is useful for commands that would otherwise wait indefinitely for user input in a non-interactive context (like a script run by cron, where no one is present to type anything).

Redirecting Standard Input: <

The < operator redirects a file’s content to be used as a command’s stdin, as if you had typed the file’s content at the keyboard:

$ sort < unsorted_names.txt
Alice
Bob
Carol
Dave

This sorts the content of unsorted_names.txt and displays the sorted result — without sort needing to know or care that the input came from a file rather than the keyboard.

When < Matters vs. Providing a Filename Directly

Many commands accept a filename directly as an argument, making < unnecessary in those cases:

$ sort unsorted_names.txt        # Command reads the file directly
$ sort < unsorted_names.txt      # Equivalent result via input redirection

For commands like sort, grep, cat, and most text-processing tools, both approaches work identically. The < redirection becomes essential specifically for commands that only read from stdin and have no concept of a “filename argument” — though such commands are relatively rare, < still appears frequently in scripts for clarity or when working with commands that specifically expect input via stdin (like some interactive tools being fed pre-written responses).

Practical Example: mysql Command Requiring Input

$ mysql -u root -p database_name < schema.sql

The mysql command line client is designed to read SQL commands from stdin; feeding it a .sql file via < is the standard way to execute a script of SQL commands.

Here Strings: <<<

A here string provides a single string as stdin without needing an actual file:

$ grep "pattern" <<< "some text containing pattern here"
some text containing pattern here

$ wc -w <<< "This is a five word sentence"
6

This is a convenient shortcut when you have a string value (perhaps from a variable) that you want to feed to a command expecting stdin, without creating a temporary file or using echo piped through:

$ VARIABLE="test content"
$ grep "test" <<< "$VARIABLE"
test content

Equivalent to (but more concise than):

$ echo "$VARIABLE" | grep "test"

Here Documents: << (Multi-Line Input)

For multi-line input, a here document (heredoc) provides content until a specified delimiter is reached:

$ cat << EOF
This is line one.
This is line two.
This is the last line.
EOF
This is line one.
This is line two.
This is the last line.

Heredocs are covered extensively in the article on creating text files from the command line — they are especially useful for generating multi-line configuration files or feeding multi-line input to interactive commands within scripts.

Combining Redirection with Pipes

Redirection and pipes (covered in depth in a companion article) frequently combine in the same command:

$ cat access.log | grep "ERROR" > errors_only.txt

Here, a pipe connects cat to grep, and then the final result is redirected to a file rather than displayed on screen.

$ some_command 2>&1 | tee output.log

This redirects stderr to join stdout, then pipes the combined stream to tee, which simultaneously displays it on screen AND saves it to output.log.

Practical Redirection Patterns

Logging a Script’s Complete Output

#!/bin/bash
exec > script_output.log 2>&1
echo "Starting process..."
some_command_that_might_fail
echo "Process complete."

The exec > file 2>&1 at the top of a script redirects all subsequent output (from every command in the script) to the file, without needing to add redirection to each individual line.

Separating Success and Failure Logs

#!/bin/bash
process_files > success.log 2> failure.log

This creates two separate logs: successful operations in one file, error messages in another — useful for quickly checking whether anything went wrong without wading through successful output.

Silencing a Command While Checking Its Success

if command_to_test &> /dev/null; then
    echo "Success"
else
    echo "Failed"
fi

Creating a Timestamped Log Entry

echo "$(date): Backup started" >> /var/log/backup.log
tar -czf backup.tar.gz /home/sarah/ >> /var/log/backup.log 2>&1
echo "$(date): Backup completed" >> /var/log/backup.log

Redirecting Input from a Here Document Into a Remote Command

$ ssh user@server << 'EOF'
cd /var/www
git pull
systemctl restart nginx
EOF

This sends multiple commands to be executed on the remote server via SSH, using a heredoc to supply them as if typed interactively.

File Descriptor Numbers: A Deeper Look

Understanding that 0, 1, and 2 are just numbers referring to specific I/O channels clarifies redirection syntax that otherwise seems arbitrary.

$ command 0< input.txt 1> output.txt 2> errors.txt

This is the fully explicit form: 0< for stdin (the 0 is usually omitted since it’s the default for <), 1> for stdout (the 1 is usually omitted since it’s the default for >), and 2> for stderr (the 2 must always be specified since it is not the default).

Custom file descriptors beyond 0, 1, 2 can also be used for advanced scripting, though this is a more specialized technique:

exec 3> custom_output.log    # Open file descriptor 3 pointing to a file
echo "This goes to fd 3" >&3
exec 3>&-                     # Close file descriptor 3

Most everyday use of redirection only requires 0, 1, and 2 — custom file descriptors are primarily useful in complex scripts needing multiple simultaneous output streams.

Redirection Order and Evaluation

Redirections are evaluated left to right, which matters when multiple redirections target related destinations:

$ command > file.txt 2>&1     # stdout to file, then stderr follows stdout (both to file) — CORRECT
$ command 2>&1 > file.txt     # stderr follows stdout (to terminal), then stdout to file — stderr stays on terminal

This ordering rule was covered earlier but bears repeating because it is the single most common redirection mistake.

Quick Reference: Redirection Operators

Operator Effect
> Redirect stdout to file, overwriting existing content
>> Redirect stdout to file, appending to existing content
2> Redirect stderr to file, overwriting
2>> Redirect stderr to file, appending
&> Redirect both stdout and stderr to file, overwriting
&>> Redirect both stdout and stderr to file, appending
> file 2>&1 Traditional method to combine stdout and stderr to one file
2>&1 Redirect stderr to wherever stdout currently points
< Redirect file content as stdin to a command
<< Heredoc: provide multi-line input until delimiter
<<< Here string: provide a single string as input
/dev/null Special file that discards anything written to it
command < /dev/null Provide empty input (avoid hanging waiting for input)

Common Redirection Mistakes

Wrong Order for Combining Streams

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

Accidentally Overwriting Important Data

$ echo "note" > important_file.txt    # Destroys existing content without warning

Enable noclobber in your shell to prevent this:

set -o noclobber    # Add to ~/.bashrc

With noclobber set, > refuses to overwrite an existing file; use >| to force it when genuinely intended.

Trying to Read and Write the Same File in One Command

$ sort file.txt > file.txt    # WRONG: often produces an empty file!

The shell opens file.txt for writing (truncating it to zero length) before sort has a chance to read its original content — resulting in data loss. The correct approach uses a temporary file or sponge (from moreutils):

$ sort file.txt > temp.txt && mv temp.txt file.txt
# or with sponge (soaks up input before writing, avoiding the truncation issue)
$ sort file.txt | sponge file.txt

Conclusion: Directing the Flow of Information

Redirection is one of the foundational mechanisms that makes the Linux command line so powerful for both interactive use and automation. The ability to precisely control where a command’s output goes — a file, another command, nowhere at all — transforms simple commands into building blocks for logging, monitoring, data processing, and scripted automation.

The essential operators to internalize: > for capturing output (with its overwrite behavior worth remembering), >> for appending, 2> for isolating error messages, and 2>&1 or &> for combining streams when you want everything captured together. Once these become second nature, you gain precise control over exactly what happens to every byte of output your commands produce — an essential skill for effective shell scripting and command-line work.

Hot this week

Type Traits in C++: Compile-Time Type Information

Master C++ type traits — learn how to query and transform types at compile time using , write your own type traits, and use them with if constexpr and SFINAE.

What Is the Difference Between sh, bash, and zsh Shells?

Learn the difference between sh, bash, and zsh shells in Linux — their history, compatibility, features, and how to choose the right shell for scripting and daily use.

How to View File Contents in Linux Without Opening an Editor

Learn how to view file contents in Linux using cat, less, more, head, tail, and other commands — without opening a text editor. Perfect for quick checks and log monitoring.

Understanding Pipes in Linux: Chaining Commands Together

Learn how Linux pipes work, how to chain commands together with the | operator, practical pipe examples, and the difference between pipes and redirection.

What Is the Linux Shell Profile and Bashrc File?

Learn the difference between .bashrc, .bash_profile, .profile, and /etc/profile in Linux — which files run when, what to put in each, and how to customize your shell startup.

Topics

Type Traits in C++: Compile-Time Type Information

Master C++ type traits — learn how to query and transform types at compile time using , write your own type traits, and use them with if constexpr and SFINAE.

What Is the Difference Between sh, bash, and zsh Shells?

Learn the difference between sh, bash, and zsh shells in Linux — their history, compatibility, features, and how to choose the right shell for scripting and daily use.

How to View File Contents in Linux Without Opening an Editor

Learn how to view file contents in Linux using cat, less, more, head, tail, and other commands — without opening a text editor. Perfect for quick checks and log monitoring.

Understanding Pipes in Linux: Chaining Commands Together

Learn how Linux pipes work, how to chain commands together with the | operator, practical pipe examples, and the difference between pipes and redirection.

What Is the Linux Shell Profile and Bashrc File?

Learn the difference between .bashrc, .bash_profile, .profile, and /etc/profile in Linux — which files run when, what to put in each, and how to customize your shell startup.

How to Create and Edit Text Files from the Command Line

Learn every way to create and edit text files from the Linux command line — touch, cat, echo, redirection, heredocs, and terminal editors like nano and vim.

Understanding Linux Software Sources and PPAs

Learn what PPAs are, how Ubuntu software sources work, how to safely add and remove PPAs, and the risks and benefits of using third-party software repositories.

How to Search for Installed Packages in Linux

Learn how to check if a package is installed in Linux and list all installed packages using dpkg -l, rpm -qa, apt list --installed, and dnf list installed.

Related Articles

Popular Categories