I have JSON output as shown below (the output of lsblk
, greatly simplified). I need to generate CSV output which shows the name of a disk, together with a list of mount points, if any. I can generate this for simple cases, but the problem is that there's a recursive children list, containing additional mountpoints, which I don't know how to handle.
There are a couple of other SO questions which ask specifically about parsing lsblk
output, but they show a simpler (old?) lsblk
output, which is flat (and with mountpoints which aren't arrays).
For the example below, I'd like to get CSV output that looks like (without the comments, obviously):
"sda" # no mountpoints
"sdb","foo1","foo2","foo3" # no top-level mountpoint, 3 [grand]children
Note:
mountpoints
are arrays. Presumably they can contain more than one element (or no elements), but I've never seen thismountpoints
can contain null
entries, but it seems like the array is always presentblockdevices
object contains a list, but only entries of type disk
are relevantAny help much appreciated - I've spent several hours trying to find a walk/recurse solution which handles the children.
{
"blockdevices": [
{
"type": "disk",
"name": "sda",
"etc" : "ignore",
"mountpoints": [ null ]
},{
"type": "loop",
"etc" : "ignore everything"
},{
"type": "disk",
"name": "sdb",
"etc" : "ignore",
"mountpoints": [ null ],
"children": [
{
"name": "ignore",
"etc" : "ignore",
"mountpoints": [ "foo1" ]
},{
"name": "ignore",
"etc" : "ignore",
"mountpoints": [ null ],
"children": [
{
"name": "ignore",
"etc" : "ignore",
"mountpoints": [ "foo2" ]
},{
"name": "ignore",
"etc" : "ignore",
"mountpoints": [ "foo3" ]
}
]
}
]
}
]
}
Probably not the cleanest way, but we could:
select(.type == "disk")
to prevent empty starting arrays...
) get all .mountpoints
// []
))flatten
the arrays to get a single output.null
from the arrays (values
)..blockdevices[] | select(.type == "disk") | [
.name,
(.. | (.mountpoints? // []) | flatten[] | values)
]
output:
[
"sda"
]
[
"sdb",
"foo1",
"foo2",
"foo3"
]