On 18/08/2014 12:29, Stroller wrote:

On Mon, 18 August 2014, at 10:42 am, wraeth <wra...@wraeth.id.au> wrote:

On Mon, 2014-08-18 at 18:54 +1000, Adam Carter wrote:
But this matches if grep fails both times as well as when it matches both
time. Any ideas?

If you don't mind using a quick loop, you could use something like:

n=0
for f in file1.txt file2.txt file3.txt file4.txt; do
    grep 'string' ${f} >> /dev/null && n=$[n+1]
done

if [[ $n == 4 ]]; then
    do_something
fi

I've solved similar problems the same way myself, but I hope you'll forgive me 
for offering unsolicited critique on a small detail.

In the above 4 is a constant, and thus it's independent of the number of files 
being tested.

I propose addressing this with an array of the filenames.

Thus additional files can be added for testing, without manual adjustment of 
the expected total.

   files=("file1.txt" "file2.txt" "file3.txt" "file4.txt")
   n=0
   for f in ${files[@]}; do
      grep 'string' ${f} >> /dev/null && n=$[n+1]

I would write `grep -q -m1 -F 'string' ...` here. In particular, -m1 will short-circuit after finding one match.

   done

   if [[ $n == ${#files[@]} ]]; then
      do_something
   fi

Bash array syntax is a bit arcane, but at least these very useful data 
structures are available.

Here's a slightly different take. It avoids multiple grep invocations, which could be a good thing in the case of a lengthy file list.

    files=(file1.txt file2.txt file3.txt file4.txt)
    string="matchme" # Using -F below as it's a string, not a regex

    count=0
    while read -r matches; do
        (( count += matches ))
    done < <(grep -hcm1 -F "$string" ${files[*]})

    if (( count == ${#files[@]} )); then
        do_something
    fi

--Kerin


Reply via email to