0

I am currently trying to parse the output of lsblk with jq and filters it based on some criteria.

Given the following example output:

{
   "blockdevices": [
      {
         "name": "/dev/sda",
         "fstype": null,
         "size": "931.5G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/sda1",
               "fstype": "ntfs",
               "size": "50M",
               "mountpoint": null
            },{
               "name": "/dev/sda2",
               "fstype": "ntfs",
               "size": "439.8G",
               "mountpoint": null
            },{
               "name": "/dev/sda3",
               "fstype": "vfat",
               "size": "512M",
               "mountpoint": "/boot/efi"
            },{
               "name": "/dev/sda4",
               "fstype": "ext4",
               "size": "491.2G",
               "mountpoint": "/"
            }
         ]
      },{
         "name": "/dev/sdb",
         "fstype": "crypto_LUKS",
         "size": "200GG",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/d1",
               "fstype": "btrfs",
               "size": "200G",
               "mountpoint":[
                  null
               ]
            }
         ]
      },{
         "name": "/dev/sdc",
         "fstype": "crypto_LUKS",
         "size": "100G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/abc2",
               "fstype": "btrfs",
               "size": "100GG",
               "mountpoint": "/mnt/test"
            }
         ]
      }
   ]
}

I want to go over all top-level devices that have fstype "crypto_LUKS". Then, for those devices, I want to check if the children (if present) have a mountpoint (not null). Finally I want to return the name of the toplevel device that matches both the criteria.

So for the example above, only 1 match would be returned: /dev/sdc /dev/mapper/d1.

The /dev/sdc device wouldnt be returned because the mountpoint of the children device is null/empty.

I already got this so far:

lsblk -Jpo NAME,FSTYPE,SIZE,MOUNTPOINT | jq -r '.blockdevices[] | select(.fstype == "crypto_LUKS") '

But this only checks for the crypto_LUKS critera, and not for the mountpoints of the children. Also it does print the whole array entry instead of just the two values.

How can I solve this?

2

1 Answer 1

4

To get the name of the block device and each of its non-null child mount-points as a tab-delimited list:

jq -r '
    .blockdevices[]  | select(.fstype == "crypto_LUKS") as $dev |
    $dev.children[]? | select(.mountpoint | type == "string") as $mp |
    [ $dev.name, $mp.name ] | @tsv'

Since a "null mount-point" is not actually null but an array of a single null value, I'm instead testing whether the mount-point is a string or not.

Given the data in the question, this would return

/dev/sdc        /dev/mapper/abc2

To get the block device objects that fulfill the criteria (if that's what you mean by "the whole array"):

jq '.blockdevices[] |
    select(.fstype == "crypto_LUKS" and
           any(.children[]?; .mountpoint | type == "string"))'

This returns the block device object that has the fstype value crypto_LUKS and that has at least one children element with a mountpoint that is a string.

Given the data in the question, this would return

{
  "name": "/dev/sdc",
  "fstype": "crypto_LUKS",
  "size": "100G",
  "mountpoint": null,
  "children": [
    {
      "name": "/dev/mapper/abc2",
      "fstype": "btrfs",
      "size": "100GG",
      "mountpoint": "/mnt/test"
    }
  ]
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .