list=/errors_exception.txt
cd /test
while IFS= read -r pattern ; do
for file in * ; do
if zcat < "$file" | grep -Fxq "$pattern"; then
echo "$pattern found pattern in $file"
fi
done
done <"$list" > output
Notes:
Neither of the two lines below will do what you expect:
for PATTERN in `cat $LIST`
for FILE in $(ls)
In both case, the shell does word splitting which you don't want. The suggested code above avoids this.
Is the file errors_exception.txt
really in the root directory?
I converted the variables to lower case. This is the convention for user created variables. This convention will prevent you from accidentally overwriting some critical shell parameter.
More on word splitting
When the shell executes:
for PATTERN in `cat $LIST`
it runs cat $LIST
. When it does that, spaces, tabs, and carriage returns are all treated as the same thing: a word break. So, effectively, after the word splitting, this line becomes:
for PATTERN in one one two three four five six
and, as the for
loop executes, PATTERN
is assigned sequentially to one, one, two, three, four, five, and six.
What you really want is for each line to be treated as a line. This is why the while read.... done<"$list"
construct is used instead: on each loop, it reads one whole line.
The same issue would happen with this line is any file names have spaces in them:
for FILE in $(ls)
The results of ls
are substituted into the line and, if any file names have spaces, tabs, or carriage returns in them (all of these are legal characters), then the names are split into parts. For example, in an otherwise empty directory create one file:
$ touch "a b c"
Now, run a for
loop:
$ for file in $(ls); do echo $file; done
a
b
c
The for
loops is run three times even though there is only one file. That is because the file name has spaces and, after word splitting, the for
loop gets three arguments: a, b, and c.
This is easily avoided. Use instead:
for file in *
The shell is smart enough to keep each file name here in tact regardless of what characters are in its name.
Recursive Searching
If we also want to search subdirectories for gzipped files, then we can use bash's globstar feature as follows:
list=/errors_exception.txt
cd /test
shopt -s globstar
while IFS= read -r pattern ; do
for file in **/*.gz ; do
if zcat < "$file" | grep -Fxq "$pattern"; then
echo "$pattern found pattern in $file"
fi
done
done <"$list" > output
This requires bash
.