0

With xmllint I check all XML files in the folder and if xmllint finds an invalid XML file there is an output.

My question: how can I write this output to a log file?

I found this command on the Internet:

find -type f -name "die_xml_datei.xml" -exec xmllint --noout {} \;

Here are my attempts:

find -type f -name "die_xml_datei.xml" -exec xmllint --output xml_not_valide.txt 2>&1
find -type f -name "die_xml_datei.xml" -exec xmllint --output xml_not_valide.txt {} \;
find -type f -name "die_xml_datei.xml" -exec xmllint --output > xml_not_valide.txt {} \;

1 Answers1

0

The output you're after is printed to stdout. Each xmllint will inherit the stdout from find, so the simplest approach is just to redirect the stdout of find:

find -type f -name "*.xml" -exec xmllint --noout {} \; 2>xml_not_valide.txt

However if find prints anything to stdout then it will be written to the file as well.

A single xmllint can take more than one file to check. Reduce the number of new processes by running xmllint for as many arguments as possible:

find -type f -name "*.xml" -exec xmllint --noout {} + 2>xml_not_valide.txt

If you want to redirect stderr from xmllint process(es) but not from find then you need to run an additional shell:

: >xml_not_valide.txt
find -type f -name "*.xml" -exec sh -c '
   xmllint --noout "$@" 2>>xml_not_valide.txt
' find-sh {} +

Note I used >> because find -exec sh … + does not guarantee there will be only one sh. Note each redirection with > truncates the file. We want to truncate once at the very beginning, so we redirect the output of null command :; after this >> is the way to go.


If you need to know problematic files without the detailed output of xmllint, make use of its exit status. The tool will return non-zero if there are problems, zero otherwise. Use -exec … \; as a (negated) test:

find -type f -name "*.xml" ! -exec xmllint --noout {} \; -print 2>/dev/null >xml_not_valide.txt

Only if ! -exec … succeeds (e.i. if -exec … fails, i.e. if xmllint returns non-zero), find will -print. It will print to stdout. We silence what xmllint prints to stderr and keep what find prints to its stdout.

You cannot do this with -exec … +. This time you must run one xmllint per file.