1

My goal is to output a JSON object using jq on the output of a find command in bash. It could either be a one-line command or a bash script.

I have this command which creates JSON objects from each line of output:

find ~/ -maxdepth 1 -name "D*" | \
while read line; \
do jq -n \
--arg name "$(basename "$line")" \
--arg path "$line" \
'{name: $name, path: $path}'; \
done

The output looks like this:

{
  "name": "Desktop",
  "path": "/Users/username/Desktop"
}
{
  "name": "Documents",
  "path": "/Users/username/Documents"
}
{
  "name": "Downloads",
  "path": "/Users/username/Downloads"
}

But I need these objects to be in an array, and I need the array to be the value of a a parent object's single key called items, like so:

{"items": [
    {
      "name": "Desktop",
      "path": "/Users/username/Desktop"
    },
    {
      "name": "Documents",
      "path": "/Users/username/Documents"
    },
    {
      "name": "Downloads",
      "path": "/Users/username/Downloads"
    }
  ]
}

I tried adding the square brackets to the jq output string for each line ('[{name: $name, path: $path}]';) and that adds the brackets but not the commas between the array elements.

I found possible solutions here but I could not figure out how to use them while looping through each line.

5

This trick with the jq 1.5 inputs streaming filter seems to do it

... | jq -n '.items |= [inputs]'

Ex.

$ find ~/ -maxdepth 1 -name "D*" | 
    while read line; do 
      jq -n --arg name "$(basename "$line")" --arg path "$line" '{name: $name, path: $path}'
    done | jq -n '.items |= [inputs]'
{
  "items": [
    {
      "name": "Downloads",
      "path": "/home/steeldriver/Downloads"
    },
    {
      "name": "Desktop",
      "path": "/home/steeldriver/Desktop"
    },
    {
      "name": "Documents",
      "path": "/home/steeldriver/Documents"
    }
  ]
}
1
  • Thank you, this works. Also, when seeing your example output I realized that I'd made a mistake in the example output that I included... it showed an invalid list of arrays for the value of the items field. I corrected the question just now. Your example produces a single array of objects, which is what I needed. – Employee Feb 26 '20 at 21:34
0

If you dont mind using a programming language, this is pretty simple. Here is an example with PHP:

<?php
$m1 = [
   'items' => []
];
$a1 = glob('~/D*');
foreach ($a1 as $s1) {
   $m1['items'][] = [
      'name' => basename($s1),
      'path' => $s1
   ];
}
echo json_encode($m1, JSON_PRETTY_PRINT);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.