4

I was using this line to find the phrase, 'B206' within files in the directory I was in and all of its sub directories.

find . -exec grep -s "B206" '{}' \; -print 

It crashes when it tries to read certain files and actually changes the title bar in putty to a bunch of weird characters

For example, it crashes all the time when it hits a jpg file that's in a sub directory. The title bar changes, and in the screen, there exists:

ÐF»*rkNQe×ばつ3kU£~MÞçÄZ1⁄2aéúýØâÑn¡[U+Þ4aÒ9/ê£<ú ̄4}[IÓ­îÃ\K»G%Ý3¢

Forcing me to Ctrl+C out back to the prompt and then exit out.

Any way to add code to this line that will exclude jpg files? Even better, a piece of code where I can add a list of extensions to exclude?


EDIT:
-not & -I do not work for me
I found this similar question also related somewhat to mine

asked Jun 22, 2009 at 15:41
2
  • what is your environment? bash? tcsh? linux distro? os x? Commented Jun 22, 2009 at 16:21
  • If your system is POSIX compliant, you can substitute -not with ! Further, if the string you are seeking is always surrounded by non-word characters (including newline), you may be able to use the -w switch to grep [NB: this switch is not specified by POSIX, so YMMV]. I'd also use the -H flag for grep to ensure it prints the filename: find . ! -iname "*.jpeg" ! -iname "*.jpg" ! -iname "*.png" -exec grep -Hw B206 {} \; Commented Feb 3, 2012 at 15:45

12 Answers 12

8

There's no reason to use find: grep comes with a recursive option, -r. To just get a list of the filenames with matches (as opposed to a list of all of the matching lines in all the files), you can use the -l option. If you want to ignore all binary files outright, you can use --binary-files=without-match option. If you only want to ignore files with a certain extension, you can use the --exclude option, e.g. --exclude=*.{jpg,jpeg} to ignore all files ending in .jpg or .jpeg. Thus, you should be able to get what you want with this:

grep -r -l --binary-files=without-match .

Now, you mentioned in one of your comments that your version of grep doesn't have the -r or -l options. That's unfortunate, and I recommend getting a more recent version of grep (preferably of the GNU variety).

One further note: if you use find -exec, you should use a + to end the command instead of a semicoln, e.g.:

find . -exec grep options '{}' '+'

By using a +, find will only fork off a single process and pass all of the matching filenames as command line arguments to one instance of grep. So long as you don't have a million matching files (which would create a command line far longer than the shell can handle), this will be much, much faster. If you use a semicolon instead, find forks a new process for each matching file, which is really slow for a very large number of files.

answered Jun 22, 2009 at 16:08
Sign up to request clarification or add additional context in comments.

1 Comment

Only GNU grep comes with -r (recursive), true UNIX grep doesn't. You must either install GNU grep or use it with find.
4

If your environment can't do any fancy grep, maybe your awk can do it:

find . | awk '!/((\.jpeg)|(\.jpg)|(\.png))$/ {print 0ドル;}' | xargs grep "B206"
answered Jun 22, 2009 at 16:54

2 Comments

Can you post an example? Maybe it might deserve a question itself.
3

You can use grep's -I switch:

Process a binary file as if it did not contain matching data;
this is equivalent to the --binary-files=without-match option.

In short, grep will simply assume the file doesn't match, which will keep binary data from being output.

answered Jun 22, 2009 at 15:51

2 Comments

first of all, your name is great... second of all - could you give me an example of the syntax?
If his grep doesn't support '-not', it seems unlikely GNU grep will be available and -I is a GNU addition to grep.
3

Just a quote, you don't need to close the terminal, you can use the command reset to restore the terminal output mode.

You can also do a previous grep to remove the extensions you don't want:

find -print | grep -v '\(\.jpg\|\.bmp\)$' | xargs grep "B206"
answered Jun 22, 2009 at 16:36

Comments

2

I tried Erik's command but I got an error about no -grep predicate. Perhaps my version of find is too old.

This worked for me:

find . -type f -a -not -name \*.jpg -exec grep "B206" {} \;
answered Jun 22, 2009 at 15:58

Comments

2
find . -type f -a -not -name \*.jpg -exec grep -li "string" "{}" \;

This example comes from Mac OSX 10.5, you will need to check the find man page for your environment since there is some divergence between GNU find and other vendor implementations. Checking Solaris ( just for fun, the target OS was never specified ):

find . -type f -a ! -name \*.jpg -exec grep -li "string" "{}" \;

This construction finds all files whose names do not end in .jpg and execs grep for each of them.

Depending on your shell, you may need to escape the bang (!) in order for this to work as advertised.

answered Jun 22, 2009 at 15:47

3 Comments

-ls is not understood either - this is nuts
What OS/version are you using?
not sure.... your second command seems to be working... any way to modify it to exclude all the lines that say 'grep: can't open...' and/or 'find: cannot open...'?
2

Given the recent lovefest over ack, I'm surprised no one's mentioned it yet.

You can configure types by extension so that you 'grep' just the files you want. Or you can just use --nobinary, given the problem you've been facing.

answered Jun 22, 2009 at 17:07

Comments

1

If you have access to gfind, simply add "-not -name '*.jpg'" to the expression.

gfind . -not -name '*.jpg' -exec grep -s "B206" '{}' \; -print

Another option (not needed for this task but a useful trick) is, if you want to use really fancy regexps, to do

find some_easy_high_level_filter_expression -ls | perl -pe '{ /your_Perl_RegExp_of_choice/ }'> ./files_to_search_in

grep options 'cat ./files_to_search_in'

# preceding line should have backticks but I can't get the formatter to escape them

This gives the sometimes-needed benefit of caching the file list in case you want to change the grep expression to fin-tune it or just do more than 1 grep.

answered Jun 22, 2009 at 15:53

1 Comment

my version doesn't know what the -not is. i get the bad option error msg
1
grep -r --exclude=*.jpg B206 .

Sorry, from another comment:

Only GNU grep comes with -r (recursive), true UNIX grep doesn't. You must either install GNU grep or use it with find. – Terminus

answered Jun 22, 2009 at 16:13

Comments

1

I think the problem is when you grep a binary file, it outputs binary data. That binary data somehow gets interpreted in your shell.

I would suggest to try to use the command "strings" that makes sure that your output is text-only first, and then grep on the output of "strings."

answered Jun 22, 2009 at 16:19

Comments

1

To use grep with find, my syntax is:

find . -name "*" -print | xargs grep B206

All the options to filter files, binary and all, then the results are passed as arguments to the grep command.

Jeremy Wiebe
3,96325 silver badges31 bronze badges
answered Jun 22, 2009 at 16:15

1 Comment

this still gets hung up on that jpg
0

grep -I -r "string" *

answered Jun 22, 2009 at 15:55

2 Comments

i MUST have an old/shitty version of Unix.... i get these errors from this command... grep: illegal option -- I grep: illegal option -- r
Only GNU grep comes with -r (recursive), true UNIX grep doesn't. You must either install GNU grep or use it with find.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.