Detect invalid JSON files in directory tree

It looks like jsonlint cannot deal with multiple files:

$ jsonlint -h

Usage: jsonlint [file] [options]

file     file to parse; otherwise uses stdin

Note that it always says file, never files. When you run a command and pipe its output to xargs as you have done, xargs will simply concatenate all the output of the command and pass it as input to whatever you have told it to execute. For example:

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

That shows you that the command executed by xargs was

echo foo bar baz

In the case of jsonlint, what you want to do is not jsonlint -q foo bar baz but

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

The easiest way to do this is to use find as suggested by @fede.evol:

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

To do it with xargs you need to use the -I flag:

   -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.

For example:

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

Or, to deal with strange names (that contain newlines for example) safely:

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

The current answers to this question are incomplete since the suggested commands will not print the name of the invalid file. Also, jsonlint is one hell of a slow tool.

Here's a much much faster alternative which shouldn't require additional installations on most systems:

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


Use the "-exec" option to execute on each find recurrence. The recurrence file is passed as {} and use \; to finish the command.

So something like:

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

On the output you could do an inverse grep of ": ok". something like:

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

This will return false if there is one not ok or true if there is. The 2>&1 is ugly but errors are written to stderr at least on my jsonlint version