Reformatando um grande número de arquivos XML

10

Estou manipulando um grande número de arquivos XML espalhados por uma estrutura de diretório aninhada.

Eu tentei o seguinte:

$ find . -name "*.xml" -type f | xargs -- xmllint --format

O problema é que gera a saída XML formatada na tela, mas não altera o arquivo.

Como posso alterar este comando para que o conteúdo atual do arquivo seja alterado?

    
por Harry 08.10.2012 / 09:38

2 respostas

21

Isso pode ser feito diretamente de find usando -exec :

find . -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;

O que é transmitido para -exec será chamado uma vez por arquivo encontrado com os parâmetros de modelo {} sendo substituído pelo nome do arquivo atual. O \; no final do comando find termina a linha.

O uso de xargs não é realmente necessário neste caso, porque precisamos invocar xmllint uma vez por arquivo, pois os nomes dos arquivos de entrada e saída devem ser especificados dentro da mesma chamada.

xargs seria necessário se o comando que estava sendo enviado do find estivesse trabalhando em vários arquivos por vez e essa lista fosse longa. Você não pode fazer isso nesse caso, já que precisa passar o nome de arquivo único para a opção --output de xmllint . Sem xargs você pode acabar com um erro "Argument List too long" se estiver processando muitos arquivos. xargs também suporta strings de substituição de arquivos com a opção -I :

find . -name "*.xml" -type f | xargs -I'{}' xmllint --output '{}' --format '{}'

Faria o mesmo que o comando find -exec acima. Se alguma das suas pastas tiver caracteres estranhos em espaços semelhantes, você precisará usar as opções -0 de find e xargs . Mas usar xargs com -I implica na opção -L 1 , que significa processar apenas um arquivo de cada vez, portanto, você também pode usar diretamente find com -exec .

    
por 08.10.2012 / 09:43
5

Eu normalmente ataco esses problemas com uma camada de indireção. Escreva um script de shell que faça o que você quer e chame isso. Eu sugeriria como um começo

#! /bin/sh
for file
do
   xmllint --format $file > $file.tmp && mv $file.tmp $file
done

O teste em um arquivo ou dois à mão, então você pode substituí-lo no xargs

find . -name "*.xml" -type f | xargs -- xmltidy.sh
    
por 08.10.2012 / 09:43

Tags