Read Linux Block Devices Reliably with lsblk

A disk vanishes or mounts somewhere odd, and lsblk is the fastest way to see why. It lists disks, partitions, filesystems and mount points without touching any of them. This guide covers a readable inventory, filesystem identity, script-friendly output, and the timing quirks that catch people out right after a hardware change. Examples use the lsblk binary found first on this machine, from util-linux 2.41.3; the local manual page documents util-linux 2.39.3, so options are checked against that and the version gap is called out where it actually matters.

Give it ten minutes. You need a shell and the util-linux package. These commands only read device metadata: no mounting, formatting, partitioning or repair, and normally no elevated privileges. Root only comes into it if udev has no usable metadata and lsblk has to read filesystem information straight off a device.

1. Confirm which lsblk you are running

A distro package and a separately installed util-linux can quietly ship different versions of the same command, so check first:

$ command -v lsblk
/home/linuxbrew/.linuxbrew/bin/lsblk
$ lsblk --version
lsblk from util-linux 2.41.3
$ dpkg-query -W -f='${Package} ${Version}\n' util-linux
util-linux 2.39.3-9ubuntu6.6

Your paths and version will differ. Those first two lines tell you exactly which binary your shell is about to run; if you expected the distribution copy, check your PATH before comparing output or writing a script against it.

Checkpoint: run lsblk --help and confirm the options you plan to use are actually listed there. Available output columns come from lsblk --help on the 2.39.3 manual, or lsblk --list-columns on the 2.41.3 binary.

2. Get a readable inventory

With no device named, lsblk reports available block devices, RAM disks normally excluded. The default tree view is fine for a glance, but its columns and layout are not a stable interface, so ask for what you actually need:

$ lsblk --list --output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS
NAME  TYPE   SIZE FSTYPE MOUNTPOINTS
loop0 loop  13.1M        /snap/canonical-livepatch/414
sda   disk   3.6T
sda1  part    16G
md2   raid1  3.6T        /

Your devices and mounts will be different, so do not expect these exact rows. --list gives one row per device with no relationship tree. NAME is the short device name; TYPE tells disk from partition from loop from software RAID. MOUNTPOINTS can list more than one mount point, while the singular MOUNTPOINT shows only one, usually the most recent.

Add --paths for full device paths:

$ lsblk --list --paths --output NAME,TYPE,SIZE,MOUNTPOINTS
NAME       TYPE   SIZE MOUNTPOINTS
/dev/sda   disk   3.6T
/dev/sda1  part    16G

A blank mount-point field does not mean an unused device. It could be unmounted, a container member, or a device whose filesystem metadata simply is not available yet.

3. Inspect filesystem identity

--fs gives a convenient overview: type, label, UUID, free space, mount points:

$ lsblk --fs
NAME   FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda
|-sda1 ext4   1.0         11111111-2222-3333-4444-555555555555    8G    42% /

Those values are illustrative. Never copy a UUID out of an example into /etc/fstab; take it from your own output, and remember the manual points to blkid as the authoritative tool for detailed filesystem and RAID identification.

For something narrower and easier to review, pick columns explicitly:

$ lsblk --list --output NAME,PATH,FSTYPE,LABEL,UUID,MOUNTPOINTS
NAME PATH      FSTYPE LABEL UUID                                 MOUNTPOINTS
sda  /dev/sda
sda1 /dev/sda1  ext4         11111111-2222-3333-4444-555555555555 /

Still read-only, and it still does not prove a UUID is unique across every disk you might attach later. Check the full inventory before wiring an identifier into persistent config.

4. Produce output a script can trust

Define both the columns and the format for anything automated. JSON is easy for a program to parse:

$ lsblk --json --output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS > /tmp/lsblk.json
$ head -12 /tmp/lsblk.json
{
   "blockdevices": [
      {
         "name": "loop0",
         "type": "loop",
         "size": "13.1M"
      }

Add --tree alongside JSON when the consumer needs parent and child relationships; the manual explicitly recommends always specifying --output, and reaching for --tree when hierarchy matters. Treat every value as a string unless your parser deliberately handles missing fields and human-readable sizes.

For shell scripts, --pairs --shell gives quoted, sourceable-looking output:

$ lsblk --pairs --shell --output NAME,TYPE,SIZE
NAME="loop0" TYPE="loop" SIZE="13.1M"
NAME="sda" TYPE="disk" SIZE="3.6T"

Warning: do not execute this output as shell code. Parse the quoted values instead, or use a language with a proper parser. Device labels and mount points are data, not something you should ever treat as trusted commands.

5. Handle timing and failures

A device that was just added or changed may not have complete udev data yet. If output looks incomplete right after a hardware event, wait for udev before asking again:

$ sudo udevadm settle
$ lsblk --list --output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS

udevadm settle may need elevated privileges and can block waiting for outstanding events. It changes no partitions or filesystems, but it does wait on device processing, so use it deliberately rather than sprinkling it into every script.

Check the exit status whenever a specific device is named:

$ lsblk --list /dev/does-not-exist
lsblk: /dev/does-not-exist: not a block device
$ printf 'status: %s\n' "$?"
status: 32

Capture the status immediately, before anything else overwrites it.

Keep the safety boundary clear

lsblk is an inventory command, full stop. It does not make anything safe to format, detach or overwrite. Before any separate destructive operation, re-query the path, size, filesystem and mount points fresh, and stop if the result is ambiguous. There is no undo for a mistaken format or partition change, and that is outside the scope of this guide entirely.

If a script depends on the output, avoid the default display and avoid parsing human-readable sizes. Pin the columns with --output, pick --list, --json or --pairs deliberately, and test against machines with no mount point, several mount points, and software RAID.

Done means