2

This question already has an answer here:

I have some binaries and some .c extension files in my directory.

Here the output using ls

arrays.c basic0 basic0.c fromfb fromfb.c oute oute.c segmen.c simp simp.c

Here i want to filter binary files only , so I use

ls |grep -v .c

This command list all files, Then using grep I get files, except those file not ending with .c

What I expect is

basic0
fromfb
oute
simp

But What i got

fromfb
oute
simp

basic0 binary file missing. What is the problem with this?

marked as duplicate by Wildcard, HalosGhost, sam, GAD3R, Satō Katsura Nov 10 '16 at 18:47

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • try ls | grep -v "\.c" ("\." escapes dot sign) – bob_saginowski Nov 10 '16 at 12:23
  • @Wildcard , iam not like to finding binary files, I just want to why grep behave like this.So this not duplication :) – SuperKrish Nov 10 '16 at 13:35
  • ls | grep is almost always not what you want. You probably want find. – HalosGhost Nov 10 '16 at 14:12
  • this question is more about grep than binaries. I'll vote Leave Open. – Archemar Nov 10 '16 at 14:21
  • 1
    Sounds like we have an "X" and a "Y" problem; a confusion regarding grep, and a desire to "find binary files only" – Jeff Schaller Nov 10 '16 at 14:53
10

As per man grep

The period . matches any single character.

thus grep .c match any character followed by c

You might be looking for grep -v \.c or better grep -v '\.c$'

where

  • \. escape special meaning of .
  • c
  • $ end of line (when piped to ls output one file name par line)

as suggested by wildcard, you can also use grep -vF .c The -F flag tells grep to use arg as simple string, not regular expression.

  • Or just grep -F .c to keep it simple. – Wildcard Nov 10 '16 at 13:43
1

You need to escape the dot sign with "\.". Try with ls | grep -v "\.c$". Executing grep -v .c means any record that does not contain the charater c preceded by another character

  • @EricRenouf thank you, just edited my answer :) – bob_saginowski Nov 10 '16 at 12:35
1

man

man grep tells us that

The period . matches any single character.

This means that .c matches any single character followed by a c. Since you haven't anchored your expression, this matches any string that contains any character followed by a c.

Let's test that. What if we don't use the -v flag?

test

Let's see. First, we set up a test

~ $ mkdir test
~ $ cd test
~/test $ touch arrays.c
~/test $ touch basic0
~/test $ touch basic0.c
~/test $ touch fromfb
~/test $ touch fromfb.c
~/test $ touch oute
~/test $ touch oute.c
~/test $ touch segmen.c
~/test $ touch simp
~/test $ touch simp.c
~/test $ ls
arrays.c  basic0.c  fromfb.c  oute.c    simp
basic0    fromfb    oute      segmen.c  simp.c

Then we test ls | grep .c:

~/test $ ls|grep .c
arrays.c
basic0
basic0.c
fromfb.c
oute.c
segmen.c
simp.c

As you can see, not only do the intended C sources match, but the binary file basic0 matches as well. The i is matched by the . and the c is matched by (no surprise here) the c.

solution

You want to match C sources to exclude them. These files end with .c, so we tell grep to match those.

~/test $ ls|grep "\.c$"
arrays.c
basic0.c
fromfb.c
oute.c
segmen.c
simp.c

We've done two things here. First, we've escaped the dot, to make it a literal dot instead of "any single character". But this would still match a file called foo.c.bar which may or may not be your goal.
Assuming it's not, we've also anchored the c to be the last character. Now you're matching the strings that end with a dot and a c.

Reapplying -v is left as an exercise for the reader.

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