Обнаружение недопустимых файлов JSON в дереве каталогов
Я хочу завершить сборку, если дерево каталогов содержит файл JSON, который является недопустимым в соответствии с jsonlint
пакет из НПМ.
Я думал, что это будет так же просто, как запустить:
find . -name \*.json | xargs jsonlint -q
Я знал, что у меня был плохо сформированный документ JSON на диске, и это не подхватывает его.
Дальнейшее расследование показывает, что find
Команда работает, как и ожидалось, однако jsonlint
Исполняемый файл вызывается только один раз (и первый файл JSON верен).
Есть ли лучший способ сделать это, или есть что-то, что мне нужно узнать о xargs
Вот?
Я использую Ubuntu 13.10 Server и могу устанавливать пакеты при необходимости.
4 ответа
Это выглядит как jsonlint
не может иметь дело с несколькими файлами:
$ jsonlint -h
Usage: jsonlint [file] [options]
file file to parse; otherwise uses stdin
Обратите внимание, что это всегда говорит файл, а не файлы. Когда вы запускаете команду и передаете ее вывод xargs
как вы сделали, xargs
просто объединит все выходные данные команды и передаст их в качестве входных данных тому, что вы сказали выполнить. Например:
$ printf "foo\nbar\nbaz\n"
foo
bar
baz
$ printf "foo\nbar\nbaz\n" | xargs echo
foo bar baz
Это показывает, что команда выполнена xargs
было
echo foo bar baz
В случае jsonlint
то, что вы хотите сделать, это не jsonlint -q foo bar baz
но
$ jsonlint -q foo
$ jsonlint -q bar
$ jsonlint -q baz
Самый простой способ сделать это - использовать find
как предложено @ fede.evol:
$ find . -name \*.json -exec xargs jsonlint -q {} \;
Сделать это с xargs
вам нужно использовать -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.
Например:
$ find . -name \*.json | xargs -I {} jsonlint -q {}
Или для безопасного обращения со странными именами (например, с символами новой строки):
$ find . -name \*.json -print0 | xargs -0I {} jsonlint -q '{}'
Текущие ответы на этот вопрос являются неполными, поскольку предлагаемые команды не будут печатать имя неверного файла. Кроме того, jsonlint - чертовски медленный инструмент.
Вот гораздо более быстрая альтернатива, которая не требует дополнительных установок на большинстве систем:
find . -name \*.json -exec echo {} \; -exec python -mjson.tool "{}" \; 2>&1 | grep "No JSON" -B 1
Используйте параметр "-exec" для выполнения при каждом повторении поиска. Файл повторения передается как {} и используется \; закончить команду.
Так что-то вроде:
find . -name \*.json -exec jsonlint {} \;
На выходе вы можете сделать обратный grep ": ok". что-то вроде:
find . -name "*.txt" -exec jsonlint -v {} \; 2>&1 | grep -q -v ": ok"
Это вернет false, если есть один не в порядке или true, если есть. 2>&1 некрасиво, но ошибки записываются в stderr по крайней мере в моей версии jsonlint
Недавно мне также захотелось обнаружить и проанализировать все мои файлы JSON (игнорируя при этом определенный каталог). Я не смог найти нужный мне инструмент, поэтому создал собственный модуль Python и разместил его на pypi: https://pypi.org/project/JsonFNL/.