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