114

I am using the following command on a Unix server:

find . -type f -name "*.txt" | xargs grep -li 'needle'

Since grep -R is not available, I have to use this find/xargs solution. Every time a file cannot be opened, grep tells me this:

grep: can't open "foo.txt"

I want to get rid of this message, so I tried to redirect stderr to /dev/null, but somehow this is not working.

find . -type f -name "*.txt" | xargs grep -li 'needle' 2>/dev/null

I want to preserve stdout (i.e. write the results to the console), and only hide these grep error messages. Instead of 2>, I also tried &>, but this also did not work. How can I fix this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
r0f1
  • 2,717
  • 3
  • 26
  • 39
  • 1
    What kind of shell are you using? – csl Jun 26 '17 at 11:46
  • 3
    Literally pages of answers: [Redirect stderr to /dev/null site:stackoverflow.com](http://www.google.com/search?q=Redirect+stderr+to+%2Fdev%2Fnull+site%3Astackoverflow.com) – jww Jun 26 '17 at 19:36
  • 1
    Yes, but that is too unspecific. It is better to find a candidate for a canonical question and point to that (and vote or flag this as a duplicate). – Peter Mortensen Feb 21 '20 at 18:53
  • Related (though that is all output), from 2009: *[How can I suppress all output from a command using Bash?](https://stackoverflow.com/questions/617182)* – Peter Mortensen Feb 21 '20 at 20:26

2 Answers2

170

In order to redirect stderr to /dev/null use:

some_cmd 2>/dev/null

You don't need xargs here. (And you don't want it! since it performs word splitting)

Use find's exec option:

find . -type f -name "*.txt" -exec grep -li needle {} +

To suppress the error messages use the -s option of grep:

From man grep:

-s, --no-messages Suppress error messages about nonexistent or unreadable files.

which gives you:

find . -type f -name "*.txt" -exec grep -lis needle {} +
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • Thank you @hek2mgl that solution works perfectly :) All the grep warnings are gone (regardless whether or not I use the -s flag). Also didn't know about the `-exec` possiblity. – r0f1 Jun 26 '17 at 11:49
19

Just move the redirection to the first command, i.e.

find ... 2>/dev/null | xargs ...

Or you can enclose everything in parenthesis:

(find ... | xargs ...) 2>/dev/null
csl
  • 10,937
  • 5
  • 57
  • 89
  • Thank you, but this also does not work :S (find . -type f -name "*.txt" | xargs grep -li 'needle') 2>/dev/null Badly placed ()'s. find . -type f -name "*.txt" 2>/dev/null | xargs grep -li 'needle' Ambiguous output redirect. – r0f1 Jun 26 '17 at 11:41