How do I find files that do not contain a given string pattern?

FileGrepDirectoryFind

File Problem Overview


How do I find out the files in the current directory which do not contain the word foo (using grep)?

File Solutions


Solution 1 - File

If your grep has the -L (or --files-without-match) option:

$ grep -L "foo" *

Solution 2 - File

You can do it with grep alone (without find).

grep -riL "foo" .

This is the explanation of the parameters used on grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

If you use l (lowercased) you will get the opposite (files with matches)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

Solution 3 - File

Take a look at ack. It does the .svn exclusion for you automatically, gives you Perl regular expressions, and is a simple download of a single Perl program.

The equivalent of what you're looking for should be, in ack:

ack -L foo

Solution 4 - File

The following command gives me all the files that do not contain the pattern foo:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

Solution 5 - File

The following command excludes the need for the find to filter out the svn folders by using a second grep.

grep -rL "foo" ./* | grep -v "\.svn"

Solution 6 - File

If you are using git, this searches all of the tracked files:

git grep -L "foo"

and you can search in a subset of tracked files if you have ** subdirectory globbing turned on (shopt -s globstar in .bashrc, see this):

git grep -L "foo" -- **/*.cpp

Solution 7 - File

You will actually need:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep :0\$

Solution 8 - File

I had good luck with

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

My attempts with grep -v just gave me all the lines without "foo".

Solution 9 - File

Problem

I need to refactor a large project which uses .phtml files to write out HTML using inline PHP code. I want to use Mustache templates instead. I want to find any .phtml giles which do not contain the string new Mustache as these still need to be rewritten.

Solution

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

Explanation

Before the pipes:

Find

find . Find files recursively, starting in this directory

-iname '*.phtml' Filename must contain .phtml (the i makes it case-insensitive)

-exec 'grep -H -E -o -c 'new Mustache' {}' Run the grep command on each of the matched paths

Grep

-H Always print filename headers with output lines.

-E Interpret pattern as an extended regular expression (i.e. force grep to behave as egrep).

-o Prints only the matching part of the lines.

-c Only a count of selected lines is written to standard output.


This will give me a list of all file paths ending in .phtml, with a count of the number of times the string new Mustache occurs in each of them.

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

The first pipe grep :0$ filters this list to only include lines ending in :0:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

The second pipe sed 's/..$//' strips off the final two characters of each line, leaving just the file paths.

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

Solution 10 - File

When you use find, you have two basic options: filter results out after find has completed searching or use some built in option that will prevent find from considering those files and dirs matching some given pattern.

If you use the former approach on a high number of files and dirs. You will be using a lot of CPU and RAM just to pass the result on to a second process which will in turn filter out results by using a lot of resources as well.

If you use the -not keyword which is a find argument, you will be preventing any path matching the string on the -name or -regex argument behind from being considered, which will be much more efficient.

find . -not -regex ".*/foo/.*" -regex ".*"

Then, any path that is not filtered out by -not will be captured by the subsequent -regex arguments.

Solution 11 - File

My grep does not have any -L option. I do find workaround to achieve this.

The ideas are :

  1. to dump all the file name containing the deserved string to a txt1.txt.

  2. dump all the file name in the directory to a txt2.txt.

  3. make the difference between the 2 dump file with diff command.

     grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
     grep * *.log | cut -c1-14 | uniq > txt2.txt
     diff txt1.txt txt2.txt | grep ">"
    

Solution 12 - File

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

You can specify the filter under "find" and the exclusion string under "grep -vwE". Use mtime under find if you need to filter on modified time too.

Solution 13 - File

Open bug report

As commented by @tukan, there is an open bug report for Ag regarding the -L/--files-without-matches flag:

As there is little progress to the bug report, the -L option mentioned below should not be relied on, not as long as the bug has not been resolved. Use different approaches presented in this thread instead. Citing a comment for the bug report [emphasis mine]:

> Any updates on this? -L completely ignores matches on the first line of the file. Seems like if this isn't going to be fixed soon, the flag should be removed entirely, as it effectively does not work as advertised at all.


The Silver Searcher - Ag (intended function - see bug report)

As a powerful alternative to grep, you could use the The Silver Searcher - Ag:

> A code searching tool similar to ack, with a focus on speed.

Looking at man ag, we find the -L or --files-without-matches option:

> ... > > OPTIONS > ... > > -L --files-without-matches > Only print the names of files that don´t contain matches.

I.e., to recursively search for files that do not match foo, from current directory:

ag -L foo

To only search current directory for files that do not match foo, simply specify --depth=0 for the recursion:

ag -L foo --depth 0

Solution 14 - File

another alternative when grep doesn't have the -L option (IBM AIX for example), with nothing but grep and the shell :

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

Solution 15 - File

This may help others. I have mix of files Go and with test files. But I only need .go files. So I used

ls *.go | grep -v "_test.go"

> -v, --invert-match select non-matching lines see https://stackoverflow.com/a/3548465

Also one can use this with vscode to open all the files from terminal

code $(ls *.go | grep -v "_test.go")

Solution 16 - File

grep -irnw "filepath" -ve "pattern"

or

grep -ve "pattern" < file

above command will give us the result as -v finds the inverse of the pattern being searched

Solution 17 - File

The following command could help you to filter the lines which include the substring "foo".

cat file | grep -v "foo"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSenthil KumarView Question on Stackoverflow
Solution 1 - Fileghostdog74View Answer on Stackoverflow
Solution 2 - FileAdrianView Answer on Stackoverflow
Solution 3 - FileAndy LesterView Answer on Stackoverflow
Solution 4 - FileSenthil KumarView Answer on Stackoverflow
Solution 5 - Fileuser999305View Answer on Stackoverflow
Solution 6 - FileZakView Answer on Stackoverflow
Solution 7 - FileForrest TiffanyView Answer on Stackoverflow
Solution 8 - FileJohnnyView Answer on Stackoverflow
Solution 9 - FileGruffyView Answer on Stackoverflow
Solution 10 - FileDaniel J.View Answer on Stackoverflow
Solution 11 - Fileuser6305682View Answer on Stackoverflow
Solution 12 - FilezandeepView Answer on Stackoverflow
Solution 13 - FiledfribView Answer on Stackoverflow
Solution 14 - FileJMDView Answer on Stackoverflow
Solution 15 - FileARIF MAHMUD RANAView Answer on Stackoverflow
Solution 16 - FileJayView Answer on Stackoverflow
Solution 17 - FilewalkerlinView Answer on Stackoverflow