Ambos awk e sed são geralmente inadequados para analisar XML (e outros formatos semelhantes, como JSON e YAML, etc.). Para este exemplo de XML, por exemplo, não sabemos qual ordem os nós em InvoiceLines estão armazenados ou se eles são delimitados por novas linhas ou não. O formato XML não se preocupa com essas coisas, mas um script awk ou sed cairia facilmente a menos que cuidados excepcionais fossem tomados para cobrir todos os casos possíveis (incluindo as várias codificações possíveis dos dados), caso em que você faria Teria que escrever um analisador XML de qualquer maneira.
Portanto, usar um analisador de XML, como o construído em xmlstarlet , é a coisa certa a se fazer.
O comando a seguir deve imprimir o nome do arquivo de entrada se pelo menos um dos nós requeridos for encontrado no arquivo file.xml . Se vários InvoiceLines nós correspondessem, o nome do arquivo seria impresso várias vezes com uma nova linha no meio. Isso significa que, desde o início, desqualificamos nomes de arquivos contendo novas linhas.
xmlstarlet sel \
-t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
--inp-name -nl file.xml
A consulta XPATH corresponderia a todos os InvoiceLines que tinham subnós chargeType e charge com os valores especificados. Usar o @charge em vez do charge teria sido testado contra um atributo charge no nó InvoiceLines , a propósito.
Aplicando isso em todos os arquivos XML em um único diretório:
xmlstarlet sel \
-t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
--inp-name -nl ./*.xml
Se houver muitos arquivos e os itens acima gerarem um erro, você poderá usar xargs :
printf '%s\n' ./*.xml | xargs xmlstarlet -t -m ...
Ou find (também será pesquisado subdiretórios):
find . -type f -name '*.xml' -exec xmlstarlet -t -m ... {} +
canalize o resultado até uniq se quiser tornar a listagem de arquivos única.
Eu usei o seguinte XML para testar o acima:
<BillingData>
<InvoiceLinesList>
<InvoiceLines>
<chargeType>D</chargeType>
<charge>99</charge>
</InvoiceLines>
<InvoiceLines>
<chargeType>D</chargeType>
<charge>99</charge>
</InvoiceLines>
<InvoiceLines>
<chargeType>E</chargeType>
<charge>99</charge>
</InvoiceLines>
</InvoiceLinesList>
</BillingData>