How to Redirect All Output to a File in Bash
You run a command that produces output and errors, and you want to save everything to a file for later review. How do you capture both stdout and stderr in Bash?
TL;DR
To redirect all output (both stdout and stderr) to a file, use command &> file.txt or command > file.txt 2>&1. The first syntax is simpler and works in Bash 4+. To append instead of overwrite, use command &>> file.txt. To send output to a file while still seeing it on screen, use command 2>&1 | tee file.txt.
Understanding Bash redirection helps you capture output, suppress errors, or split different output streams as needed.
Let's start with a simple command that produces both normal output and errors:
ls /home /fakedir
This outputs:
/home:
user1 user2
ls: cannot access '/fakedir': No such file or directory
The directory listing goes to stdout (file descriptor 1), and the error goes to stderr (file descriptor 2).
Basic Output Redirection
Redirect standard output (stdout) only:
ls /home /fakedir > output.txt
This saves the directory listing to output.txt, but the error still shows on screen. The file contains:
/home:
user1 user2
And the error still appears in your terminal.
Redirecting Stderr
Redirect only errors (stderr):
ls /home /fakedir 2> errors.txt
Now the directory listing shows on screen, but the error is saved to errors.txt.
Redirecting Both Stdout and Stderr
To capture everything in one file, use one of these methods:
Modern syntax (Bash 4+):
ls /home /fakedir &> output.txt
The &> redirects both stdout and stderr to the same file.
Traditional syntax (works everywhere):
ls /home /fakedir > output.txt 2>&1
This redirects stdout to output.txt, then redirects stderr (2) to wherever stdout (1) is going (the file).
Command output flow:
stdout (1) ----> output.txt
stderr (2) ----> follows stdout ----> output.txt
The order matters - 2>&1 must come after > output.txt.
Appending vs Overwriting
Use > to overwrite a file:
echo "first" > file.txt
echo "second" > file.txt
# file.txt now contains only "second"
Use >> to append:
echo "first" >> file.txt
echo "second" >> file.txt
# file.txt now contains "first" and "second"
For both stdout and stderr:
# Overwrite
command &> output.txt
# Append
command &>> output.txt
Or with traditional syntax:
# Append both
command >> output.txt 2>&1
Discarding Output
Send output to /dev/null to discard it:
# Discard stdout only
command > /dev/null
# Discard stderr only
command 2> /dev/null
# Discard both
command &> /dev/null
This is useful when you don't care about the output:
# Run a command silently
wget http://example.com/file.zip &> /dev/null
Separating Stdout and Stderr
To save stdout and stderr to different files:
command > output.txt 2> errors.txt
Now normal output goes to output.txt and errors go to errors.txt.
Seeing Output and Saving It
Use tee to both display output and save it:
# Show on screen and save to file
command | tee output.txt
For both stdout and stderr:
command 2>&1 | tee output.txt
This redirects stderr to stdout, then pipes everything through tee, which writes to the file and displays on screen.
To append instead of overwrite:
command 2>&1 | tee -a output.txt
Redirecting Output from Scripts
Inside a script, redirect all output:
#!/bin/bash
# Redirect everything this script outputs
exec &> /var/log/myscript.log
echo "This goes to the log file"
ls /fakedir # Error also goes to log
The exec command redirects all subsequent output from the script.
To redirect only a section:
#!/bin/bash
echo "This shows on screen"
{
echo "This goes to file"
ls /fakedir
} &> section-output.txt
echo "This shows on screen again"
Practical Example: Deployment Script
A deployment script that logs everything:
#!/bin/bash
set -e
LOG_FILE="/var/log/deploy-$(date +%Y%m%d-%H%M%S).log"
# Redirect all output to log file
exec &> "$LOG_FILE"
echo "=== Deployment started at $(date) ==="
echo "Pulling latest code..."
git pull origin main
echo "Installing dependencies..."
npm install
echo "Building application..."
npm run build
echo "Restarting service..."
sudo systemctl restart myapp
echo "=== Deployment completed at $(date) ==="
# Also display the log location on screen (goes to stderr of the exec)
echo "Deployment log saved to: $LOG_FILE" >&2
Practical Example: Cron Job Logging
Cron jobs should redirect output to avoid email notifications:
# In crontab
0 2 * * * /home/user/backup.sh &>> /var/log/backup.log
This appends both stdout and stderr to the log file.
Or discard output completely:
0 2 * * * /home/user/cleanup.sh &> /dev/null
Redirecting in Complex Commands
With pipes:
# Both stdout and stderr through the pipe
command 2>&1 | grep error
# Only stderr through the pipe (swap file descriptors)
command 3>&1 1>&2 2>&3 | grep error
With command substitution:
# Capture stdout in a variable, stderr goes to screen
OUTPUT=$(command)
# Capture both stdout and stderr in a variable
OUTPUT=$(command 2>&1)
Understanding File Descriptors
Bash uses these file descriptors by default:
0 - stdin (standard input)
1 - stdout (standard output)
2 - stderr (standard error output)
When you use redirection:
command 2>&1
This means "redirect file descriptor 2 (stderr) to file descriptor 1 (stdout)".
You can create custom file descriptors:
# Open file descriptor 3 for writing to a file
exec 3> custom.log
# Write to it
echo "Log entry" >&3
# Close it
exec 3>&-
Common Patterns
Run command silently:
command &> /dev/null
Save output, show errors:
command > output.txt
Save errors, show output:
command 2> errors.txt
Save both separately:
command > output.txt 2> errors.txt
Save both together:
command &> combined.txt
Append both:
command &>> combined.txt
Show and save:
command 2>&1 | tee output.txt
Debugging Redirection
To see what's being redirected, add -x to your script:
#!/bin/bash
set -x # Enable debugging
ls /home /fakedir &> output.txt
This shows the actual command execution with redirection visible.
Common Mistakes
Wrong order:
# Wrong - stderr goes to screen, not to file
command 2>&1 > output.txt
# Right - stderr follows stdout to file
command > output.txt 2>&1
The order matters because redirections are processed left to right.
Forgetting to quote filenames with spaces:
# Wrong
command > my output.txt # Creates files "my" and "output.txt"
# Right
command > "my output.txt"
Using > when you meant >>:
# This overwrites the log every time!
echo "$(date) Error occurred" > app.log
# This appends, keeping history
echo "$(date) Error occurred" >> app.log
Redirecting Within Subshells
Redirections in subshells don't affect the parent:
# This redirect only affects the subshell
(command &> output.txt)
# Parent shell's stdout is unchanged
echo "This still shows on screen"
When to Use Each Method
Use > file when:
- You only need stdout
- Errors should show on screen
Use 2> file when:
- You only want to capture errors
- Normal output should show on screen
Use &> file when:
- You want everything in one file
- You're reviewing logs later
Use | tee file when:
- You want to see output immediately
- You also want a copy in a file
Use > /dev/null when:
- You don't care about output
- You want commands to run silently
Mastering Bash redirection gives you precise control over where output goes. Whether you're logging scripts, debugging errors, or running cron jobs, understanding these patterns helps you capture exactly what you need.
Found an issue?