grep -c exits non-zero on zero matches
This looks like sensible defensive shell, and it has a bug:
n=$(grep -c pattern file || echo ERR)
When nothing matches, grep -c prints 0 and exits 1. The || branch
fires anyway, so $n becomes 0 followed by ERR on the next line — the
"error" fallback corrupts a perfectly good count.
The root cause is grep's three-way exit status:
0— at least one match1— no matches (not an error!)2— an actual error (unreadable file, bad pattern)
So exit 1 must be treated as success when counting. Either drop the fallback
entirely:
n=$(grep -c pattern file) || true
or distinguish real errors explicitly:
n=$(grep -c pattern file)
case $? in
2) echo "grep failed" >&2; exit 1 ;;
esac
The general lesson: || guards assume "non-zero means failure," and several
classic tools (grep, diff, cmp) use exit codes as ternary answers, not
pass/fail.