You may not be using these outputs to their full potential, or to their intended meaning. You never want to mix debugging & diagnostic output with actual results of your program.
Standard output: the intended result of the program, for example, list of files (ls), modified or processed text file (sed,grep,awk), a compressed file in response to input file (bzip,gzip), any stream-based filtering of processing that you might want to do, result of your calculation, and so on. You may be used to outputting directly into files, but that's a worse practice, because standard output is meant to be pipelined. You can have a long chain of tools that pass their output to the input of the next one via pipe
|, eventually redirecting
> the final output to the file of your choice, or even discarded (if the output is long, you probably don't want it to go directly into the terminal window). It's easy to redirect standard output to a file in the shell, it's much harder to convince a program that writes to a file, to talk to other tools.
Error output: This is meant so that the program can gossip about what it's doing. For example, outputting which file it's processing right now, percentage of completion, timestamps of when it started a certain stage of computing, warning, and error messages. During development, you usually output a lot to
stderr, so that you catch any problems as soon as possible, and so you know where it gets stuck and deduce what went wrong. That's why
stderr is not buffered: you want it to be seen immediately on screen, because if your program dies, any buffered text may never get to the screen. Of course, you may redirect this as well to a log file, and review it later, especially if you are not standing next to the terminal (if you are running your code on a cluster, for example).
Most programs are very chatty on stderr, even the ones you may not think of, such as GUI based programs (firefox, pdf reader,...).
Because the usage of both streams is completely different, you want an easy separation of the two. A few examples:
Observe what it's doing, and saving the result
programname arguments > outputfile
Discard the messages, save the result:
programname arguments > outputfile 2> /dev/null
Save the messages for later, look at the output on console to "preview" what you'll save on the next run:
programname arguments 2> logfile
Make a chain of tools that do something in a single line, save it (but observe all the diagnostics in real time):
programname arguments | filterprogram | anotherfilter > outputfile