(apologies in advance if this one is incredibly obvious to anyone out there, i've been :wall: at this one for some time now)
What I've got is a newline-separated list of filenames to search the contents of around 2,000 XML files for, and return the name of that file. This seems like a job for a "for" loop, so I enter this on the command line:
for i in `cat ~/targets.txt`; do grep -l -m 1 $i *.xml; done
The problem here is that one of my target filenames might appear in more than one file - I only want grep to return the very first match in the very first file that it finds, and then stop and move on to the next iteration of the loop. (Which is what I was attempting to do with -m 1)
That's a useless use of backticks and useless use of cat, not just inefficient but potentially harmful -- if the file is too large it may silently return less data than is really in the file.
This construct has none of those limits:
while read LINE
do
...
done < filename
Since you have -m 1, you have GNU grep, which supports -F and -f, so a loop isn't actually necessary:
grep -m 1 -f targets.txt *.xml
If targets.txt contains fixed strings and not regexes, add -F before -f.
---------- Post updated at 02:30 PM ---------- Previous update was at 02:29 PM ----------
...and if all you care about is the filename and not what precisely is matching, -l will work instead of -m 1.
Huh! I didn't know about those gotchas with cat and the backticks (they call out exactly what I was doing there as very very wrong), so thanks for that
Unfortunately this didn't solve my problem though. It's still returning more than one file for each line in my targets.txt
grep -l -Ff targets.txt *.xml
Radoulov's script did though! I never would have thought about using a while loop in that way. It seems I have much to learn still. Thanks!!
#!/usr/bin/ksh
while read mString; do
echo "Now searching for <${mString}>"
for mFName in *.xml; do
echo "Now searching on file <$mFName>"
mCnt=$(grep -c ${mString} ${mFName})
if [[ ${mCnt} -ne 0 ]]; then
echo "Found <${mString}> on file <${mFName}>"
break
fi
done
done < Strings_File