I would like to search all files containing an association of strings (here the files should contain 'arthur' AND ('déni' OR 'deni') for instance) in a directory and subdirectories. After some search I came up with the following code:

egrep -li 'arthur' `egrep -lir 'déni|deni' /path/to/files/`

the trouble is I get error messages because many files and directories contain spaces. Is there a way to go round this issue?


You would be better off using find and passing a shell command to -exec:

find /path/to/files -type f -exec sh -c 'for file do
    egrep -iq "déni|deni" "$file" && egrep -li "arthur" "$file"
    done' sh {} +

This would work with filenames containing spaces.

Dissecting the shell command:

egrep -iq "déni|deni" "$file" && egrep -li "arthur" "$file"

Saying egrep -iq "déni|deni" "$file" would return true if the pattern matches. So it would execute egrep -li "arthur" "$file" which would list the file if this command matches the pattern specified.

In fact, you don't even need a shell:

find /path/to/files -type f -exec egrep -iq "déni|deni" {} \; \
                            -exec egrep -li "arthur" {} \;

(-exec predicates with the ; terminator can also be used as conditions (based on the exit status of the executed command)).

  • You have to quote this differently - the | will be interpreted as a pipe in the local shell as it stands. – Graeme Mar 15 '14 at 10:48
  • @Graeme The quoting should be fixed now. – devnull Mar 15 '14 at 10:51
  • ok. I am not good enough to make the difference between both command but it seems that using the find command is quicker than egrep. So I'm gonna use that one. – jejuba Mar 15 '14 at 14:53
  • 2
    @Jean, this will be slower than just using egrep/xargs as you will have 1-2 egrep processes per file. The advantage of this is that it is more portable, ie will work on a Mac etc. – Graeme Mar 15 '14 at 15:04
  • @jejuba - Graeme's solutions is probably the better of the two. – slm Mar 15 '14 at 15:15

With GNU grep you can use the -Z option to null separate the filenames before piping to xargs:

egrep -lirZ 'déni|deni' /path/to/files/ | xargs -0 egrep -li 'arthur'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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