SoftTimur
SoftTimur

Reputation: 5510

Loop through files which do not contain certain texts in makefile

I want to go through a set of files in makefile:

alltest:    all
            for f in $(FILES); do \
                echo $$f; \
            done

I want to write $(FILES) such that it regards the files of /abc/*.txt which do not contain ERROR1 or ERROR2 in their body.

Too look for a set of files which contain ERROR1 or ERROR2 in their body, I use find -iname '/abc/*.txt' | xargs grep -e "ERROR1" -e "ERROR2"

Could anyone tell me how to do the complement of the set, also how to integrate the shell command into the makefile?

Upvotes: 1

Views: 814

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753990

First things first…does this do what you think and want?

find -iname '/abc/*.txt'

It doesn't find files in a subdirectory for me (on Mac OS X 10.8.5). Where find . -iname '*.txt' finds some files, find . -iname '/path/*.txt produces no output, and neither does -ipath. However, find . -ipath '*/path/*.txt' does produce a list of files. So, for the time being, we'll correct your find command to:

find . -ipath '*/abc/*.txt'

Next, you run:

xargs grep -e "ERROR1" -e "ERROR2"

This will produce lines with both the names of the files and the message. If you wanted the names of the files which include a match, you need to add -l to the command:

find . -ipath '*/abc/*.txt' |
xargs grep -l -e "ERROR1" -e "ERROR2"

However, you want to list only the files that do not match. For that, if you have GNU grep, you can use the -L option:

find . -ipath '*/abc/*.txt' |
xargs grep -L -e "ERROR1" -e "ERROR2"

If you don't have GNU grep, then you have to work a lot harder:

find . -ipath '*/abc/*.txt' |
tee file.names |
xargs grep -l -e "ERROR1" -e "ERROR2" > matching.file.names
comm -23 file.names matching.file.names

The tee command captures a copy of the list of file names in the file file.names (such originality). The grep command captures the list of matching file names in matching.file.names. The names will be in the same order in both files. The ones that appear in file.names but not in matching.file.names are the ones you want. By default, the comm file.names matching.file.names command would print 3 columns: those lines found only in the first file, those found only in the second file, and those found in both files. By suppressing the output of columns 2 and 3 with the -23 option, we get only the names in the first file that are not found in the other — which is the list you want.

Where you take the list from there is up to you…

Upvotes: 2

Related Questions