Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I read the question about how to find out the number of files that contain a certain string. This is possible with grep -l "string" * | wc -l.

Is it possible to invert this, finding the number of files not containing the target string? I tried adding the -v option, but this doesn't seem to output the right result.

share|improve this question
up vote 10 down vote accepted

With GNU or OpenBSD grep:

grep -L "string" ./* | grep -c /
share|improve this answer

Another POSIX way:

for f in *; do
  [ -d "$f" ] && continue
  { grep -q string || c=$(($c + 1)); } < "$f"
echo "$c"

By redirecting the command group instead of grep alone, we avoid counting as 1 the files which we cannot open (like files which we don't have read permission for, or * if there's no non-hidden file in the current directory).

With GNU grep, the equivalent would be:

grep -d skip -L foo ./* | grep -c /

Note that you can't use wc -l as filenames can be made of several lines. Having ./ also avoids problems with filenames that start with - or are - (which -- doesn't work around). Note that it ignores dot files.

share|improve this answer

Here's a POSIX-compliant way, in case you don't have grep -L:

for file in *; do
    awk '/string/ { found=1; exit } END{ if(!found) { printf "x" } }' < "$file"
done | wc -c
share|improve this answer

Another POSIX way using only grep and wc:

for i in *;do COUNT_FILES=$((COUNT_FILES+1));done
MATCHES=$(grep -l "string" * | wc -l)
echo "There are $NON_MATCHES files not matching \"string\""
share|improve this answer
Note that it will return 1 if there's no non-hidden file in the current directory. You may also want to skip directories. Another way to count the files and avoid a race condition would be set -- *, use $# and loop with for i do .... You can't use wc -l to count files as filenames can be made of several lines. – Stéphane Chazelas Jan 8 '14 at 12:47

Depending on how much files you want to search through, it's a good advice to take a look at ack-grep. The reason, because ack-grep is a lot faster than good'ol grep and the CLI is nearly identical.

ack-grep -Lur "some string" * | wc -l

share|improve this answer

With zsh:

( arr=(./*(.N^e_'grep -q PATTERN $REPLY'_)); print ${#arr}; )

This saves the names of the files that don't contain PATTERN into an array and returns the number of elements in the array. It uses glob qualifiers: . selects only regular files (add D to include hidden files), N turns on null glob and the negated (^) estring: ^e_'grep -q PATTERN $REPLY'_ further deselects the file names for which the shell code between the quotes returns true.

share|improve this answer

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.