You are not logged in.
Pages: 1
I am trying to find files containing certain strings.
I can do
find -type f -exec grep string {} \;
But in this case, I want to find all files containing "string1: anything" but not the ones containing "string1: string2"
find . -type f -exec grep -q "string1:" {} \; -exec grep -v "string1: string2" {} \;
is returning files containing "string1: string2" which is the opposite of what I want.
so I tried
grep -r "string1:" ./ | grep -v "string1: string2"
but that is still listing files containing "string1: string2"
Any ideas?
Last edited by hussam (February 1 2015)
I think you have to use negative lookaheads in grep. I use grep with the perl syntax. Not sure about the bash syntax so you'll have to look it up.
I'll try:
grep -rL "string1: string2" | xargs grep "string1"
Try this:
find . -type f | grep "string1." | grep -v "string1.string2"
@hussam:
First, you don't need to use `find`, since you can use `grep -r` which will traverse directories recursively.[1]
Second, your question is asking to list files containing patterns, but the commands you run are actually listing pattern matches, not filenames.
If you want to list the name of the files matching your pattern, you have to use these options:
-L, --files-without-match
Suppress normal output; instead print the name of each input
file from which no output would normally have been printed. The
scanning will stop on the first match.-l, --files-with-matches
Suppress normal output; instead print the name of each input
file from which output would normally have been printed. The
scanning will stop on the first match.
In your case, try something like this:
grep -rl 'string1:' . | xargs grep -L 'string1: string2'
It's pretty close to your suggestion, but arguably a bit faster, if the second grep is running on a considerably smaller subset (which is highly likely).
[1]: About traversing directories recursively, you can also get by using shell features. If you're using a modern shell (like zsh or bash 4), you can use the really cool recursive globbing feature. (Note that by default, OS X uses bash 3, which is political and idiotic, but that's a rant for another day...). Anyway, my point is that you should avoid Useless Uses of Find. A good rule of thumb is, every time you use `find .`, there's probably a better way to do it.
Following up on rolf's suggestion, I tried to achieve this using lookaheads. Unfortunately, I only found how to do this using GNU grep (which is available on most linux distros, but not other unices). GNU grep has a `-P` option that supports Perl compatible regex (pcre).
You can try doing something like this:
grep -Prl 'string1:(?! string2)' .
It would probably be better on a large amount of files searched, however this comes with a warning.
-P, --perl-regexp
Interpret PATTERN as a Perl regular expression. This is highly experimental and grep -P may warn of unimplemented features.
grep -rL "string1: string2" | xargs grep "string1"
did it. It excludes "string1: string2" but matches "string1: anything else".
Joe, it's the content of the files and not their names.
I will try your suggestion
grep -Prl 'string1:(?! string2)' .
next time I need to run this. Thank you.
Last edited by hussam (February 3 2015)
Wait, @hussam. Your first (second) attempt should've worked:
grep -r "string1:" ./ | grep -v "string1: string2"
Are you sure it didn't? In that case, would it be possible to show me the actual files and patterns that made it trip? I'm genuinely curious. (Hopefully it's not private/sensitive info).
I will try your suggestion
grep -Prl 'string1:(?! string2)' .
next time I need to run this. Thank you.
Obviously, beware of removing `-l` if you want to see the content and not the filename.
I wanted to list the file name but match content.
Pages: 1