Permission denied in find: why do we need 2>&1?

5.8k views Asked by At

I was recently searching for a way to filter out 'Permission denied' errors while searching for a file using the find command, and I found this link:

How can I exclude all "permission denied" messages from "find"?

Here's an the answer that worked for me from the link:

find . -name "filename" 2>&1 | grep -v 'permission denied'

Although this answer works, I don't fully understand why we need the 2>&1 (redirection of stderr to stdout).

Doesn't the output from the command find . -name "filename" | grep -v 'Permission denied' already redirect to stdout?

2

There are 2 answers

3
Jahid On BEST ANSWER

Because the 'permission denied' message is printed in stderr not stdout.

1 is stdout

2 is stderr

& specifies that whatever following is a file descriptor not filename

2>&1 redirects stderr to stdout and enables the error message to be piped into the grep command.

If excluding permission denied message is all you need, then this will do it without using grep:

find . -name "filename" 2>/dev/null
0
Baroudi Safwen On

When using pipes you should keep in mind that only the standard output is sent to the input of the other command, that's why you need to redirect the stderr to the stdout and then send the stdout (2>&1).

 $ grep -v "permission denied"

will show the lines that do NOT contain "permission denied".
this solution works but it's far from optimal.
whenever you want to get rid of the error you shoud send it to /dev/null:

$ command 2> /dev/null

/dev/null is like a blackhole, anything you send there will just be lost.
another use of /dev/null is truncating files(for learning only, there is adequate functions to do that properly) :

   $ cat /dev/null > file

the file will be empty after issuing this command.
you should also note that the first thing the bash do is interpreting redirections for example :

    $ > foobar


will create a file foobar
let's say we want to send the stdout and the stderr of one command to a file:

$ command > file 2>&1

or

        $ command &> file

in the first example, the bash will :
1/redirect the stderr to the stdout
2/ redirect the stdout to file
3/execute command
and that's why :

    $ command 2>&1 >file


won't work as expected.
Sometimes you will want to send the stdout to output.txt and stderr to error.txt :

    $ command > ouput.txt 2> error.txt