Search strings from a file in files in a directory recursively; then print the string with a status

Hi All,

I hope somebody would be able to help me.
I would need to search a string coming from a file, example file.txt:

dog
cat
goat
horse
fish

For every string, I would need to know if there are any files inside a directory(recursively) that contains the string regardless of case.
And then should be able to create a status report file based from the result of the search, and produce the following format:
report.txt

dog|found
cat|found
goat|found
horse|missing
fish|missing

Thanks in advance!

As with all shell scripting questions: which shell (and version) do you use? Which OS (and version) do you use? And, most important of all: what have you tried already?

I hope this helps.

bakunin

1 Like

HI, I understand correctly?

grep -rowFf file ./

--- Post updated at 18:53 ---

I understood, it is necessary to deduce the absence of coincidences too.

Hi! It is an Oracle Linux Server 7.1.
I have tried the usual grep commands I can search in the site, but I have yet to see a mechanism that reads a file for strings (probably should be done using a loop) and find it recursively in a directory then prints a status.
I am still searching though.
Thanks!

I dare to suggest this monster :slight_smile:

grep -vFf <(grep -rowFf file.txt ./ | sort -t: -uk2 | cut -d: -f2 |
        awk '{print; print $0 "|found" > "report.txt"}') file.txt |
        sed 's/\([^:]*\)/\1|missing/' >> report.txt

--- Post updated at 20:40 ---

grep -vFf <(grep -rowFf file.txt ./ |
        awk -F: '!t[$2]++ {print $2; print $2 "|found" > "report.txt"}') file.txt |
        sed 's/\([^:]*\)/\1|missing/' >> report.txt

--- Post updated at 20:55 ---

I forgot about the option "-i" in command "grep"

1 Like

I LOVE monsters like nezabudka's above!

Still I'd like to strip it down a bit, given your system allows for "process substitution" and the relevant / applied grep options. Try:

grep -hirof file.txt * | sort -u | tee >(grep -vif- file.txt | sed 's/$/|missing/') | sed '/|/!s/$/|found/'
1 Like

Hi RudiC
I tried through "tee" output to the stderr, hence the my first varient with "cut", but I did not succeed.
I will write your code in my notes. Thanks

Else this awk approach might work, but - like all other proposals above - it needs to exclude file.txt from being looked into for matches. This can be achieved by either having it in a different directory path, or by applying "extended pattern matching" with the extglob shell option set ( man bash ). Try

$ shopt -s extglob
$ awk 'FNR == NR {T[$1]; next} {for (t in T) if ($0 ~ t) T[t] = 1} END {for (t in T) print t (T[t]?"|found":"|missing")}' file.txt !(file.txt)

Cutting further down process count:

grep -hirof file.txt * | sort -u | tee >(grep -vHif- file.txt) | sed '/^.*:/ {s///; s/$/|missing/; b;}; s/$/|found/'
1 Like

Definitely agreeing with you :slight_smile:
I just shook my head when I saw it ha ha!
I just thought, do what they say and trust it :slight_smile: