Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a list of ".c" (c files) in the current directory.

I have to find all the .c files in the current directory.

The command that can be used id ls *.c

But, another way is to use grep.

so if i give

 ls | grep *.c

It doesn't return any result for this command, whereas for other file types like ".java", ".txt" it gives expected results.

Is there any special meaning for "*.c" in grep command? Or may I know the reason for this behaviour?

share|improve this question
Why not just ls *.c? –  Johnsyweb Jan 16 '13 at 17:49
@Johnsyweb he is probably curious about WHY it didn't work. Not about the result. –  KurzedMetal Jan 16 '13 at 17:54
@KurzedMetal: Sure, but I'm curious as to how he (or she) got there. –  Johnsyweb Jan 16 '13 at 17:55
you probably had more than 1 file : for example file1.c file2.c file3.c file4.c. The shell expands this to : ls | grep file1.c file2.c file3.c file4.c : this means "ls | cmd". here cmd is "grep file1.c in_the_other_files_listed", which returns nothing as none of the other files contain the string "file1.c" (ls | greo this that : will ignore ls output, and grep "this" in file "that") –  Olivier Dulac Jan 16 '13 at 18:17
add comment

migrated from stackoverflow.com Jan 16 '13 at 18:19

This question came from our site for professional and enthusiast programmers.

6 Answers

up vote 6 down vote accepted

*.c is a glob pattern, while grep searches for regular expressions.

You want ls | grep '\.c$' if you want to find all files that end in .c.

grep matches any substring by default, not the whole string, so you don't need to write something that matches the beginning of the filename. If you did want to write that, it would be .* in a regular expression. . indicates "any character except for a line ending", and * indicates "any number (zero or more) of the previous expression".

Because . has a special meaning in a regular expression, if you want to match a literal ., you need to escape it with \. Because \ has a special meaning in the shell, you need to quote the regular expression with single quotes (').

To ensure that you match only at the end of the filename, you use $, which matches the end of the line.

share|improve this answer
add comment

Or use find, then get a listing if needed, e.g.

find . -name "*.c" -exec ls -al {} \;

Find is very useful.

share|improve this answer
This will go to subdirectories too BTW. –  texasbruce Jan 16 '13 at 17:56
if you want to stop it from going into subdirectories, change it to find . -maxdepth 1 -name "*.c" -exec ls -al {} \; –  nullrevolution Jan 16 '13 at 18:09
add comment

grep is searching the contents of the files for your REGEX not the file names.

share|improve this answer
This guy didn't deserve to get downvoted, it is what the command ls | grep *.c is doing if there are more than one file in the current directory, due to bash expansion, like I further explained in my answer. –  KurzedMetal Jan 16 '13 at 18:14
add comment

Please try:

ls | grep '\.c$'

The RegExp "*" ist not necessary

share|improve this answer
add comment

grep "*.c" is going to look LITERALLY for string "*.c", that is, string "asterisk dot c" without expanding it to mean "all the files with .c extension", which is why it is not finding anything in output of "ls":

# touch b.c

# ls -1 | grep "*.c"

result is empty.

If you want expansion, you should use egrep (extended grep) which does regular expressions. But here they're a tad different:

# ls -1 | egrep ".*.c"

that is, regex is: .*.c (any non-newline char multipled zero or more times, any non-newline char [you could escape it to mean literally "dot"], "c")

share|improve this answer
add comment

You need to quote asterisks:

ls | grep "*.c"

or the bash shell is going expand it and execute something like:

ls | grep 1.c 2.c 3.c

(suppossing you have files named 1.c, 2.c, 3.c in the current directory).

which is not going to give the result you are expecting.

What will actually do is search the content of 2.c and 3.c and show the lines that has the string 1.c in it, which are probably none, and that's why you get an empty output.

(I'm just explaining why did you get an empty output, like other said, *.c isn't a valid regex either)

share|improve this answer
add comment

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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