The stream that doesn't pipe by default
Pipes only carry stdout. Errors go to your screen no matter how many | stages follow. To capture, hide, or pipe errors you have to redirect stderr explicitly.
The three patterns you'll use forever
cmd 2> err.log— send stderr to a file.cmd 2>/dev/null— silence stderr.cmd 2>&1— merge stderr into stdout.
Combine them: cmd 2>&1 | grep ERROR finds errors across both streams. cmd > out.log 2>&1 captures everything into one file.
Order matters
Redirection is processed left-to-right and each &1 means "wherever fd 1 currently points." Compare:
cmd > out.log 2>&1→ stdout to file, then stderr to wherever stdout is now (= the file). Both end up in out.log.cmd 2>&1 > out.log→ stderr to wherever stdout is (= terminal), then stdout to file. Errors stay on screen!
Bash 4+ shortcut: &>
cmd &> out.log redirects both streams. cmd &>> out.log appends. Cleaner than > out.log 2>&1 when you don't need to keep them separate. Doesn't work in POSIX sh, so for portable scripts use the long form.
Redirections are evaluated from left to right
2>&1 >file differs from >file 2>&1. The first keeps stderr pointing to the old stdout, while the second redirects stdout and then duplicates that destination for stderr. Follow descriptor duplication in order.
Merging is convenient but destroys information
A combined build log is easy for a person to read, but a downstream parser can no longer separate result data from errors. Merge for the consumer that needs it, not by reflex.