How to Redirect stderr to stdout in Bash

By 

Updated on

11 min read

Bash: Redirect stderr to stdout

In Bash and other Linux shells, every running program uses three standard I/O streams. Each stream is represented by a numeric file descriptor:

  • 0 - stdin, the standard input stream.
  • 1 - stdout, the standard output stream.
  • 2 - stderr, the standard error stream.

A file descriptor is a number that identifies an open input or output resource. In an interactive session, stdin usually comes from the terminal. The program sends its regular output to stdout and error messages to stderr. By default, both stdout and stderr are displayed on the terminal.

For a conceptual introduction to all three channels and how commands inherit them, see the guide to stdin, stdout, and stderr in Linux .

When you redirect the output of a command to a file or pipe it to another command, you might notice that error messages still appear on the screen. This is because redirection typically affects only stdout, while stderr continues to go to the terminal.

This guide explains how to redirect stderr to stdout, redirect both streams to a file, and other common redirection patterns in Bash.

Quick Answer

To redirect stderr to the same file as stdout, place 2>&1 after the file redirection:

Terminal
command > file.txt 2>&1

In Bash, you can use the shorter &> form:

Terminal
command &> file.txt

The order matters. command > file.txt 2>&1 sends both streams to file.txt, while command 2>&1 > file.txt sends only stdout to the file and leaves stderr on the terminal.

Redirecting Output to a File

Streams can be redirected using the n> operator, where n is the file descriptor number. When n is omitted, it defaults to 1 (standard output).

The following two commands are equivalent. Both redirect stdout to a file:

Terminal
command > file.txt
Terminal
command 1> file.txt

To redirect standard error (stderr) to a file, use the 2> operator:

Terminal
command 2> error.txt

You can redirect stdout and stderr to two separate files:

Terminal
command 1> output.txt 2> error.txt

Redirecting stderr to stdout

When saving a program’s output to a file, it is common to redirect stderr to stdout so that everything ends up in a single file.

To redirect stderr to stdout, use 2>&1:

Terminal
command > file.txt 2>&1

In this example, > file.txt redirects stdout to file.txt, and 2>&1 redirects stderr to the current location of stdout (which is now file.txt).

Here is a safe example you can run from any directory. The first path should exist, while the second path is intentionally missing:

Terminal
ls /tmp /missing-path > /tmp/redirect-demo.txt 2>&1

Display the file:

Terminal
cat /tmp/redirect-demo.txt

The file contains the normal ls output for /tmp and the error message for /missing-path, because both stdout and stderr were redirected to the same destination.

Bash also provides the &> shorthand, which redirects both stdout and stderr to a file in a single operator:

Terminal
command &> file.txt

Both forms produce the same result. The &> syntax is shorter and preferred in Bash scripts, but 2>&1 is portable across all POSIX shells.

Redirecting stdout to stderr

The reverse direction is just as useful. A script often needs to print a diagnostic that should not mix with the data it produces, and the >&2 operator sends that line to standard error instead of standard output:

Terminal
echo "config file missing" >&2

The message still shows up on your terminal, because stderr goes there by default. The difference appears once the script output is redirected or piped: the diagnostic stays out of the data stream.

>&2 is shorthand for 1>&2, and the two forms are identical. The descriptor in front of > defaults to 1, exactly as it does with > file:

Terminal
echo "config file missing" 1>&2

You can watch the split by sending each stream to its own file:

Terminal
bash -c 'echo out; echo err >&2' > output.txt 2> error.txt

output.txt holds out and error.txt holds err. Both echo commands ran in the same shell, but >&2 moved the second message onto a different stream.

Every well-behaved script follows this convention: results on stdout, warnings and errors on stderr. That is what lets a caller pipe your script into another command without error text corrupting the data, and it is the pattern used when a script checks whether a command exists before doing real work.

Redirection Order Matters

The order of redirection operators changes the result. In the following example, only stdout is redirected to the file, even though it looks like both streams are captured:

Terminal
command 2>&1 > file.txt

Bash evaluates redirections left to right. 2>&1 first points stderr to wherever stdout is at that moment (the terminal), then > file.txt redirects stdout to the file. stderr keeps its earlier destination, the terminal.

Always place 2>&1 after the file redirection:

Terminal
command > file.txt 2>&1

A related mistake is naming the same file twice instead of using 2>&1:

Terminal
command > file.txt 2> file.txt

This does not merge the streams. Each redirection opens file.txt on its own, so the command ends up holding two descriptors that track separate write positions and both start at byte zero. Whichever stream writes second overwrites part of what the first one already wrote, leaving a file with truncated, interleaved text. Use 2>&1 instead, so both descriptors share one open file and one shared position:

Terminal
command > file.txt 2>&1

Appending Instead of Overwriting

The > operator overwrites the target file each time. To append output to an existing file, use >>:

Terminal
command >> file.txt 2>&1

This appends stdout to file.txt and redirects stderr to the same location.

To append both streams using the shorthand syntax, use &>>:

Terminal
command &>> file.txt

Appending is useful for log files where you want to accumulate output across multiple runs.

Piping stderr Through Another Command

By default, the pipe operator (|) only passes stdout to the next command. Any error messages from the first command are printed to the terminal, not sent through the pipe.

For pipeline syntax, exit statuses, and pipefail, see our guide to Linux pipes and the | operator .

To pipe both stdout and stderr, redirect stderr to stdout before the pipe:

Terminal
command 2>&1 | grep "error"

In this example, both regular output and error messages are passed to grep , which filters for lines containing “error”.

Bash also provides the |& shorthand:

Terminal
command |& grep "error"

Both forms are equivalent. Use 2>&1 | for POSIX compatibility or |& for brevity in Bash scripts.

Piping Only stderr

Sometimes you want the opposite: send the error messages through the pipe and throw the regular output away. Swapping the two operators does that:

Terminal
command 2>&1 >/dev/null | grep "denied"

Read it left to right, the way Bash does. When the shell builds a pipeline it connects stdout to the pipe first, so 2>&1 points stderr at the pipe as well. The following >/dev/null then moves stdout to /dev/null, and because stderr was already duplicated it keeps pointing at the pipe.

Here is a runnable example. The first path exists and produces normal output, while the second does not and produces an error:

Terminal
ls /etc /missing-path 2>&1 >/dev/null
output
ls: cannot access '/missing-path': No such file or directory

Only the error line comes back. The directory listing for /etc went to /dev/null. This is a practical way to filter or count failures, such as piping the errors into wc to see how many paths a command could not read.

Discarding Output with /dev/null

/dev/null is a special file that discards all data written to it. Redirecting to /dev/null silences output.

To suppress error messages while keeping regular output:

Terminal
command 2> /dev/null

To suppress all output (both stdout and stderr):

Terminal
command &> /dev/null

To keep only error messages and discard regular output:

Terminal
command > /dev/null

This pattern is common in scripts where you only want to check the exit status of a command without displaying its output.

Redirecting stderr and stdout to Different Destinations

In some cases, you may want to save errors to a log file while still displaying regular output on the screen.

To redirect only stderr to a file while stdout prints normally:

Terminal
command 2> error.log

To do the opposite, display errors on the screen while saving regular output to a file:

Terminal
command > output.log

To save both streams to separate files:

Terminal
command > output.log 2> error.log

If you need to both save and display output at the same time, use the tee command:

Terminal
command 2>&1 | tee output.log

This sends the combined output to output.log and also displays it on the terminal.

To save stdout and stderr to separate files while also showing both on the terminal, use process substitution:

Terminal
command > >(tee output.log) 2> >(tee error.log >&2)

Each stream goes through its own tee process. The >&2 inside the second redirect keeps error output flowing back to stderr on the terminal, so warnings stay visible.

Redirecting All Output in a Script with exec

To redirect every command’s output for the rest of a script, use the exec builtin at the top of the file. This avoids repeating >> log 2>&1 after every line:

backup.shsh
#!/bin/bash
exec >> /var/log/backup.log 2>&1

echo "Starting backup..."
rsync -a /data/ /backup/
echo "Done."

After the exec line, every later command’s stdout and stderr go to the log file. This pattern is common in cron jobs and long-running scripts where you want a single combined log without touching each command.

To redirect only stderr for the rest of the script, omit the first redirection:

Terminal
exec 2>> /var/log/backup.err

Redirecting stdout this way is one-way unless you save the original destination first. Copy it onto a spare descriptor, such as 3, before you redirect:

backup-with-status.shsh
#!/bin/bash
exec 3>&1
exec >> /var/log/backup.log 2>&1

echo "Starting backup..."
echo "Backup started, see /var/log/backup.log" >&3

rsync -a /data/ /backup/

exec 1>&3 3>&-
echo "Backup finished"

exec 3>&1 duplicates stdout onto descriptor 3 while it still points at the terminal. Everything after the second exec goes to the log, except the messages written explicitly to >&3, which reach the terminal instead. The closing exec 1>&3 3>&- restores stdout from the saved copy and closes descriptor 3, so the last echo prints on screen again.

Descriptors 3 through 9 are free for this kind of bookkeeping. Only 0, 1, and 2 carry fixed meanings.

Quick Reference

For a printable quick reference, see the Bash cheatsheet .

SyntaxDescription
command > fileRedirect stdout to a file (overwrite)
command >> fileRedirect stdout to a file (append)
command 2> fileRedirect stderr to a file
command 2>> fileAppend stderr to a file
command >&2Send stdout to stderr
command > file 2>&1Redirect both stdout and stderr to a file
command &> fileShorthand for redirecting both streams (Bash)
command &>> fileAppend both streams to a file (Bash)
command 2>&1 | cmdPipe both streams to another command
command 2>&1 >/dev/null | cmdPipe only stderr to another command
command |& cmdShorthand for piping both streams (Bash)
command 2> /dev/nullDiscard error messages
command &> /dev/nullDiscard all output
exec >> file 2>&1Redirect all output for the rest of a script
exec 3>&1Save the current stdout on descriptor 3

FAQ

What is the difference between > and >>?
The > operator overwrites the target file, while >> appends to it. Use >> when you want to add output to an existing file without erasing its contents.

What does 2>&1 mean?
It redirects file descriptor 2 (stderr) to the same destination as file descriptor 1 (stdout). The & before 1 tells Bash that 1 is a file descriptor, not a filename.

What is /dev/null?
/dev/null is a special device file that discards all data written to it. Redirecting output to /dev/null effectively silences the command.

Is &> the same as 2>&1?
In Bash, command &> file is equivalent to command > file 2>&1. Both redirect stdout and stderr to the same file. However, &> is a Bash extension and is not available in all POSIX shells.

How do I print to stderr in a Bash script?
Append >&2 to the command, as in echo "error message" >&2. The full form is 1>&2, and both are the same. Use it for warnings and errors so callers can pipe your script output without diagnostics mixed into the data.

How do I redirect stderr to stdout in a pipe?
Use command 2>&1 | next_command or the Bash shorthand command |& next_command. Both send stderr and stdout through the pipe.

Can I pipe only stderr and discard stdout?
Yes. Swap the operators: command 2>&1 >/dev/null | grep pattern. The 2>&1 runs first and points stderr at the pipe, then >/dev/null discards stdout.

Conclusion

Redirecting stderr and stdout helps you capture logs, filter errors, and keep scripts quiet when needed. Use 2>&1 for portable shell syntax, &> or |& for Bash shorthand, >&2 when a script needs to report a problem, and /dev/null when you intentionally want to discard output.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page