What is the difference between >, >>, 2>&1 and | in the Linux shell?
The > operator writes a command's output to a file and overwrites it, >> appends to the file, 2>&1 sends error output to the same place as normal output, and the pipe | feeds one command's output straight into the next command's input.
Explain it simply
Every command in Linux has three channels, like three taps:
- stdin (0): where input comes in, usually the keyboard.
- stdout (1): where normal output goes, usually the screen.
- stderr (2): where error messages go, also the screen by default.
Redirection lets you point these taps somewhere else. A pipe connects the output tap of one command to the input of the next, like an assembly line in a factory where each worker does one small job and passes the piece along.
Example
ls /etc > files.txt # write the list into files.txt (old content is erased)
date >> log.txt # add one line at the end of log.txt
sort < names.txt # read input from a file instead of the keyboardSeparating normal output and errors:
find / -name "*.conf" > found.txt 2> errors.txtHere the matching paths go to found.txt and the "Permission denied" messages go to errors.txt.
Sending both to one file:
./build.sh > build.log 2>&1A pipe chain that counts how many times each IP appears in a web server log and shows the top five:
cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head -5 412 10.0.0.15
198 10.0.0.42
87 192.168.1.7
40 10.0.0.9
12 172.16.0.3How it works
The numbers 0, 1 and 2 are file descriptors, small integers the process uses to refer to open files. > is short for 1>. 2>&1 means "make descriptor 2 point to wherever descriptor 1 points right now". That is why order matters: in cmd > out.txt 2>&1, stdout is first moved to the file and then stderr copies it. In cmd 2>&1 > out.txt, stderr copies the old stdout (the screen) first, so errors still appear on the screen.
A pipe a | b makes the shell create an in-memory buffer, start both commands at the same time, and connect a's stdout to the buffer's write end and b's stdin to the read end. Only stdout goes through the pipe; stderr still reaches the screen unless you redirect it too (a 2>&1 | b, or a |& b in bash).
/dev/null is a special file that throws away anything written to it, so cmd > /dev/null 2>&1 silences a command completely.
Real-world use
- Saving cron job output:
backup.sh >> /var/log/backup.log 2>&1. - Hiding noise:
find / -name app.py 2>/dev/null. - Quick log analysis with
grep | sort | uniq -c. teeto see output and save it at once:make | tee build.log.
Common mistakes
- Using
>when you meant>>and wiping a log file. - Writing
2>&1before> fileand wondering why errors still show on screen. sort file > file: the shell empties the file beforesortreads it, so you lose the data. Write to a new file instead.- Expecting a pipe to carry error messages.
What to say in the interview
"Each process has three standard streams: stdin 0, stdout 1 and stderr 2. > redirects stdout to a file and truncates it, >> appends, and 2> redirects errors. 2>&1 points stderr at wherever stdout currently goes, so cmd > file 2>&1 captures everything in one file, and the order matters. A pipe connects one command's stdout to the next command's stdin, so small tools like grep, sort and uniq can be chained to process data without temporary files."
Follow-up questions
- Why does
cmd 2>&1 > filebehave differently fromcmd > file 2>&1? - What is
/dev/nullused for? - What does the
teecommand do? - What is a named pipe (FIFO)?