Every process starts with three open channels called file descriptors. Standard input (stdin, descriptor 0) is where it reads input, normally the keyboard. Standard output (stdout, descriptor 1) is where normal results go, and standard error (stderr, descriptor 2) is where error messages go; both normally appear on your terminal. Redirection lets you connect these channels to files or to other commands instead, which is how you capture results for an exam task that says 'save the output to a file'.
The output operators are easy to confuse, so learn them precisely. > sends stdout to a file, creating it or overwriting it. >> appends stdout to the end of a file, keeping what was there. 2> sends stderr to a file, and 2>> appends stderr. < makes a file the command's stdin. Redirecting to /dev/null, a special file that discards everything written to it, is the standard way to throw away unwanted output.
find /etc -name '*.conf' > found.txt 2> errors.txt # split results and errors
find /etc -name '*.conf' > all.txt 2>&1 # both into one file
find /etc -name '*.conf' 2> /dev/null # hide permission errors
sort < names.txt # file as stdin
2>&1 means 'send descriptor 2 to wherever descriptor 1 currently points'. The shell processes redirections left to right, so order matters. cmd > file 2>&1 first points stdout at the file and then points stderr at the same place, so both land in the file. cmd 2>&1 > file points stderr at the terminal (where stdout was at that moment) and only then moves stdout, so errors still appear on screen. Bash also accepts &> file as a shortcut for sending both to a file.
A pipe, |, connects the stdout of one command to the stdin of the next, letting you build a small processing line: ps aux | grep sshd | wc -l. Only stdout travels through a pipe; stderr still goes to the terminal unless you add 2>&1 before the pipe. Pipes are the reason small tools such as grep, sort, uniq, head and wc are so useful together.
tee is the tool for when you want to see output and save it at the same time. It copies its stdin to stdout and to one or more files: df -h | tee disk.txt. Use tee -a to append instead of overwrite. tee is also the usual way to write a root-owned file from a normal account, because in sudo echo text > /etc/file the redirection is done by your own unprivileged shell and fails, whereas echo text | sudo tee /etc/file runs the writing process as root.
Key terms
- stdin, stdout, stderr
- File descriptors 0, 1 and 2: the standard input, normal output and error output of every process.
- > and >>
- Redirect stdout to a file, overwriting it (>) or appending to it (>>).
- 2>&1
- Redirect stderr to wherever stdout currently points; place it after the stdout redirection.
- Pipe (|)
- Connects one command's stdout to the next command's stdin.
- tee
- Copies its input both to the screen (stdout) and to files; -a appends.
A task says: search the whole file system for files owned by user harry and save the list to /root/harry-files, discarding errors. You run find / -user harry > /root/harry-files 2> /dev/null, then cat /root/harry-files to confirm the file contains only paths and no 'Permission denied' lines.
> file 2>&1 captures both streams in the file, but 2>&1 > file leaves errors on the terminal. Also remember a single > overwrites; use >> when the task says append.Check yourself
What is the difference between > and >>?
> truncates (overwrites) the target file, while >> adds to the end of it.
Why does sudo echo hi > /etc/motd fail for a normal user?
Your own unprivileged shell performs the redirection before sudo runs; use echo hi | sudo tee /etc/motd instead.
Does a pipe carry error messages to the next command?
No, only stdout. Add 2>&1 before the pipe if you want stderr to travel through it too.