A more detailed version of Spiff's answer:
If you have a pipeline
command1 | command2
then command 1's standard output, but not its standard error, is redirected to a pipe going to the standard input of command 2.
So if you do
command1 | command2 >/dev/null 2>&1
that sends the standard output of command 2 to /dev/null
, and sends the standard error to the same place the standard output was sent (so that it also goes to /dev/null
in this case), but it doesn't do anything with the standard error of command 1, and leaves the standard output of command 1 piped to the standard input of command 2.
However, the command
command1 2>/dev/null | command2 >/dev/null 2>&1
will send the standard output of command 1 to the standard input of command 2, the standard error of command 1 to /dev/null
, and the standard output and error of command 2 to /dev/null
, and the command
command1 2>&1 | command2 >/dev/null 2>&1
will send the standard output of command 1 to the standard input of command 2, the standard error of command 1 to the same place as the standard output of command 1 - i.e., to the standard input of command 2 - and will send the standard output and error of command 2 to /dev/null
.
So, for example
tcpdump -A -r capture.pcap 2>&1 | grep interesting-string > /dev/null 2>&1
will cause grep
to see both the standard output and error of tcpdump
(so it'll see the reading from file...
message, and match it if the interesting string is part of it), and send the standard output and error of grep
to /dev/null
, so it shouldn't produce any output, it should just give the exit status of grep
(which I presume is your intent, i.e. all you want to know is whether the interesting string is part of any of the packets).
BTW, if you are using grep
to find out whether a given string is part of its input or not, and don't want any output, try using grep -q
if your version of grep
supports it; that will run faster, because
grep
doesn't have to spend CPU time writing to /dev/null
;
grep
might quit as soon as it sees the string, so it won't spend any more CPU time reading, and tcpdump will then die with a "Closed pipe" error after grep
quits and it won't spend any more CPU time or disk/SSD bandwidth reading from the file.
(Older versions of grep
used -s
for the same purpose, but the UNIX standard says it's -q
, and most UNIX and UNIX-like systems do that now; GNU grep
, for example, uses -q
.)