Detectar arquivos JSON inválidos na árvore de diretórios

3

Eu quero falhar uma compilação se a árvore de diretórios contiver um arquivo JSON inválido de acordo com o jsonlint pacote do NPM .

Eu achei que isso seria tão fácil quanto executar:

find . -name \*.json | xargs jsonlint -q

Eu sabia que tinha um documento JSON mal formado no disco, e isso não funciona.

Outras investigações mostram que o comando find funciona como esperado, no entanto, o executável jsonlint está sendo chamado apenas uma vez (e o primeiro arquivo JSON está correto.)

Existe uma maneira melhor de fazer isso, ou há algo que eu precise aprender sobre xargs aqui?

Estou executando o Ubuntu 13.10 Server e posso instalar pacotes, se necessário.

    
por Drew Noakes 10.01.2014 / 16:47

3 respostas

4

Parece que jsonlint não consegue lidar com vários arquivos:

$ jsonlint -h

Usage: jsonlint [file] [options]

file     file to parse; otherwise uses stdin

Note que sempre diz arquivo , nunca arquivos . Quando você executar um comando e canalizar sua saída para xargs como você fez, xargs irá simplesmente concatenar toda a saída do comando e passá-la como entrada para qualquer coisa que você tenha dito para executar. Por exemplo:

$ printf "foo\nbar\nbaz\n"
foo
bar
baz
$ printf "foo\nbar\nbaz\n" | xargs echo
foo bar baz

Isso mostra que o comando executado por xargs foi

echo foo bar baz

No caso de jsonlint , o que você deseja fazer não é jsonlint -q foo bar baz , mas

$ jsonlint -q foo
$ jsonlint -q bar
$ jsonlint -q baz

A maneira mais fácil de fazer isso é usar find como sugerido por @ fede.evol:

$ find . -name \*.json -exec xargs jsonlint -q {} \;

Para fazer isso com xargs , você precisa usar o sinalizador -I :

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.

Por exemplo:

$ find . -name \*.json  | xargs -I {} jsonlint -q {}

Ou, para lidar com nomes estranhos (que contêm novas linhas, por exemplo) com segurança:

$ find . -name \*.json -print0  | xargs -0I {} jsonlint -q '{}'
    
por 10.01.2014 / 18:16
1

Use a opção "-exec" para executar em cada recorrência de localização. O arquivo de recorrência é passado como {} e use \; para terminar o comando.

Então, algo como:

find . -name \*.json -exec jsonlint {} \;

Na saída você poderia fazer um grep inverso de ": ok". algo como:

find . -name "*.txt" -exec jsonlint -v {} \; 2>&1 | grep -q -v  ": ok"

Isso retornará false se houver um não ok ou verdadeiro, se houver. O 2 > & 1 é feio, mas os erros são gravados no stderr pelo menos na minha versão jsonlint

    
por 10.01.2014 / 17:10
0

As respostas atuais para essa pergunta estão incompletas, pois os comandos sugeridos não imprimem o nome do arquivo inválido. Além disso, jsonlint é um inferno de uma ferramenta lenta.

Aqui está uma alternativa muito muito mais rápida, que não deve exigir instalações adicionais na maioria dos sistemas:

find . -name \*.json -exec echo {} \; -exec python -mjson.tool "{}" \; 2>&1 | grep "No JSON" -B 1

    
por 18.10.2018 / 13:09