As the others have said, linux provides two different output streams:
stdout, or "standard output" is where all regular output goes.
You can reference it using file descriptor 1
.
stderr, or "standard error" is a separate stream for out-of-band information.
You can reference it using file descriptor 2
.
Why two different output streams? Consider a pipeline of imaginary commands:
decrypt $MY_FILE | grep "secret" | sort > secrets.txt
Now imagine the decrypt
command fails and generates an error message. If it sent that message to stdout
, it would send into the pipe, and unless it had the word "secret" you'd never see it. So you'd end up with an empty output file, with no idea what went wrong.
However, since the pipe only captures stdout
, the decrypt
command can send its errors to stderr
, where they'll be displayed on the console.
You can redirect stdout
and stderr
, either together or independently:
# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt
You can redirect the errors to stdout
and process them as if they were normal output:
# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1
# This may be confusing. It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort
You can also use a "shorthand" notation to redirect both stdout and stderr to the same file:
decrypt $MY_FILE &> output.txt
And, finally, the >
operator will first truncate its output file before writing to it. If, instead, you want to append data to an existing file, use the >>
operator:
decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1