Com o GNU grep construído com suporte a PCRE, você poderia:
find . -size +0 -type f -exec \
grep -zLP '\A((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*+)\z' {} +
Para encontrar esses arquivos (supondo que eles não contenham bytes NUL e que cada um seja pequeno o suficiente para caber todo na memória).
Ou chame perl diretamente (permitindo arquivos com bytes NUL):
find . -size +0 -type f -exec perl -l -0777 -ne 'print $ARGV unless
/^((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*)$/' {} +
Alguns operadores específicos de perl / PCRE:
-
\Ae\zcorrespondem respectivamente no início e no final do assunto. Como^e$(ou com a opção-x), mas sem ambigüidade quando o assunto é multilinha (necessário em algumas versões do GNUgrep). -
++e*+são as versões sem retrocesso dos operadores+e*. Aqui, o mecanismo de regexp não ajuda muito a encontrar uma correspondência quando sabemos que não é possível. -
(?1)refere-se ao regexp no grupo de captura correspondente. Isso permite regexps recursivos. -
(?:...), o mesmo que(...), mas apenas para agrupamento (sem captura ...)
Note que ele encontra grandes proporções dos arquivos *.tex no meu sistema, pois < / > são usados para operadores de comparação no TeX e alguns desses caracteres são encontrados inigualáveis em comentários ou escapados.