I've been fiddling with my network card tonight, when I noticed something when I run ip link help. Here are two cases when I noticed something different:

ip link help | grep set


ip link help > ip_link_help.txt

The first command has no effect, i.e. instead of redirecting the output of ip link help from the stdout to grep, the pipe is simply ignored and the output of ip link help is sent to the stdout.

The second case is a bit different. Though ip link help ignores the redirection symbol > and just prints to the stdout, file file.txt gets created anyway (but it's empty).


ip link help prints to standard error (stderr, file descriptor 2); its standard output (stdout, file descriptor 1) gets no data. Normally the two streams go to the terminal, so you cannot really tell them apart at first glance. | or > affects standard output. After you use it you know any data that gets redirected must have been destined to stdout; everything else – to elsewhere: usually to stderr, although some programs print some data directly to the terminal (ip is not one of them).

In your first case you can redirect stderr to the file descriptor of stdout, then build a pipe:

ip link help 2>&1 | grep set

where 2>&1 tells the shell to redirect the file descriptor 2 to whatever the file descriptor 1 points to. With this syntax, if the command printed something to stdout and stderr, everything would get to grep.

In the second case the shell creates (if needed) and truncates the file before ip is run. You can see this by invoking

a_command_that_doesnt_even_exist > foo.txt

foo.txt will be created despite the obvious error. This is because it's created first, before the shell even tries to run the command.

To capture stderr to the file use 2> which redirects stderr only:

ip link help 2> ip_link_help.txt

Similarly 1> redirects stdout only. Short > you used is strictly equivalent to 1>.

An artificial example of a command that prints to the terminal in three different ways is

echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty

The output is:

standard output
standard error

You can easily redirect the first two lines. Try this:

(echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty) >stdout.txt 2>stderr.txt

This will still print the last line though.

  • @JakeGould I'm not going to start an edit war but I deliberately chose to distinguish code (actual code that's meant to be run) from random output that isn't code (it's not meant to be run; yet it benefits from being formatted like code). – Kamil Maciorowski Oct 3 '18 at 20:11
  • And it is commonly accepted here that terminal output can be displayed as ‘code’ as well. Adding quotes to code like that is really not something done on any of the Stack Exchange sites. – JakeGould Oct 3 '18 at 20:16
  • @JakeGould There's always room for improvement. :) – Kamil Maciorowski Oct 3 '18 at 20:20

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.