With enough scripting, you could surely extract the data from the XML dump, but System Profiler has a command line flag that makes it output JSON, which is much more convenient to work with:
system_profiler -json -nospawn SPApplicationsDataType -detailLevel full
And it's a bit hacky, but Apple's "Open Scripting Architecture" command line tool osascript
supports JavaScript, so it can be abused to parse and manipulate JSON without installing any third-party tools. Here's the JavaScript that converts the JSON dump to CSV:
let apps = /* [system_profiler output] */.SPApplicationsDataType;
// Collect all keys present in any row
let keys = apps.reduce((keys, app) =>
{
for(let k of Object.keys(app))
if(keys.indexOf(k) == -1)
keys.push(k);
return keys;
}, []);
// Extract values and replace missing values with empty string
let csv = apps.map(app => keys.map(k => app[k] || ''));
// Add keys as column headers
csv.unshift(keys);
// Yield the output (implicitly printed in osascript)
csv.map(row => row.map(field =>
{
// Turn all entries into strings
let s = field + '';
// Escape lines with commas, quotes and newlines
return s.match(/[,"\n]/) ? '"' + s.replace('"', '""') + '"' : s;
}).join(',')).join('\n')
Now we just replace /* [system_profiler output] */
with $(cat /dev/stdin)
, put backslashes in front of double quotes and other backslashes, cram it all into a shell string, chain the two commands together and we have a one-liner that outputs CSV:
system_profiler -json -nospawn SPApplicationsDataType -detailLevel full | osascript -l JavaScript <<<"let apps = $(cat /dev/stdin).SPApplicationsDataType; let keys = apps.reduce((keys, app) => { for(let k of Object.keys(app)) if(keys.indexOf(k) == -1) keys.push(k); return keys; }, []); let csv = apps.map(app => keys.map(k => app[k] || '')); csv.unshift(keys); csv.map(row => row.map(field => { let s = field + ''; return s.match(/[,\"\\n]/) ? '\"' + s.replace('\"', '\"\"') + '\"' : s; }).join(',')).join('\n')"
Can be piped to a file by appending something like >~/Desktop/dump.csv
.