Skip to main content
1 of 2

Bash/perl function to search `lsblk` for drives whose partitions all match a filter

The following function searches for disks whose partitions all have an attribute that match a filter when listed with lsblk. Comments are in TomDoc format.

# Public: finds drives in /dev/sd* whose partitions all have an attribute that matches a filter.
# 
# $1 - filter (default: '.*')
# $2 - attribute (default: 'MOUNTPOINT')
#
# Returns full paths to disks whose attributes match the filter
#
# Examples
#  lsblk /dev/sda -oTYPE,PATH,MOUNTPOINTS --pairs
#   #  TYPE="disk" PATH="/dev/sda" MOUNTPOINTS=""
#   #  TYPE="part" PATH="/dev/sda1" MOUNTPOINTS="/boot/efi"
#   #  TYPE="part" PATH="/dev/sda2" MOUNTPOINTS="/var/snap/firefox/common/host-hunspell\x0a/"
#  lsblk_disk_filter '(/var/snap/firefox/common/host-hunspell\\x0a/|/boot/efi)' 'MOUNTPOINTS'
#   #  /dev/sda
#
#  lsblk /dev/sda -oTYPE,PATH,FSTYPE --pairs
#   # TYPE="disk" PATH="/dev/sda" FSTYPE=""
#   # TYPE="part" PATH="/dev/sda1" FSTYPE="vfat"
#   # TYPE="part" PATH="/dev/sda2" FSTYPE="ext4"
#  lsblk_disk_filter '(ext4|xfs|vfat)' 'FSTYPE'
#   # /dev/sda
# 
# REQUIRES lsblk >= 2.33 for PATH output option - https://github.com/util-linux/util-linux/blob/master/Documentation/releases/v2.33-ReleaseNotes#L372
# TODO: add support for /dev/nvme* (I don't have hardware to test this...)
lsblk_disk_filter () {
  local filter="${1:-'.*'}";
  local attribute="${2:-'MOUNTPOINT'}"

  local PERLCMD='my ($type, $path, $attr) = /^TYPE\="([^"]*)"\s*PATH\="([^"]*)"\s*$col\="([^"]*)"\s*$/ or next; # VAR ASSIGNMENT \
  if( $type=~/disk/i){          # CHECK IF TYPE IS DISK \
    printf("%s ",$disk);          # PRINTING LAST DISK \
    $disk=$path;                 # ASSIGN NEXT DISK \
  } elsif($attr!~/$filter/){    # PARTITION ATTRIBUTE MISMATCH TEST \
    $disk="";                   # DELETING DISK ON MISMATCH \
  } END{ printf($disk); } # PRINT LAST DISK'

  lsblk --pairs --noheadings --ascii -o TYPE,PATH,$attribute /dev/sd* | perl -s -wnl -E "${PERLCMD}" -- -filter="$filter" -disk='' -col=$attribute
  # perl switch example: https://stackoverflow.com/questions/31155659/how-do-i-pass-command-line-options-to-a-perl-program-with-perl-e
  # /dev/sdx describes SCSI/SATA devices, /dev/sdx\d+ describes their partitions.
  # See the /dev/ naming convention described in the "devices" section in fdisk.
} # END lsblk_disk_filter
```