Se você quer algo por arquivo, você terá que usar um grep por arquivo, algo como:
$ find /home/somepath -type f -name '*.xml' | \
> while read path; do \
> grep -E -H -m 1 -o -Z "<tag>(.*)</tag>" "$path" || echo -e "$path\x00NULL"; \
> done
Quebrando:
$ find /home/somepath -type f -name '*.xml' -print | \
Isso gera a lista de arquivos para pesquisar e canaliza-os para o while . A única coisa que isso precisa fazer é imprimir um caminho por linha, então há muitas maneiras de fazer isso.
> while read path;do \
Isso lê cada linha na variável path shell e faz um loop até read retornar false , o que acontece quando atinge o fim do arquivo, o que ocorre quando find gerou todos os caminhos indo para.
> grep -E -H -m 1 -o -Z "<tag>(.*)</tag>" "$path" || echo -e "$path\x00NULL"; \
Isso pesquisa o arquivo atual (em $path ). Se o padrão não for encontrado no arquivo, grep retornará false (ou seja, sai com um código de saída diferente de zero), portanto, o echo é executado. O -e diz para interpretar os escapes, então o echo irá imprimir o caminho atual, um ASCII nul e o literal NULL . Isso é para emular a saída de grep , que será o caminho atual (forçado por -H , sendo grep normalmente não produzirá o caminho ao pesquisar um único arquivo), um ASCII nul (por causa do -Z ) e o texto correspondente.
> done
Fecha o loop while .