12

I'm looking for a portable way to obtain parent block device name (e.g. /dev/sda) given the partition device name (e.g. /dev/sda1). I know I could just drop the last character, but that wouldn't work in some cases:

  • MMC card readers typically have names like /dev/mmcblk0, while their partitions have names like /dev/mmcblk0p1 (notice the extra p).
  • optional: some block devices don't have any partition table at all and are formatted as a single partition. In this case, partition device and parent block device are the same.

LVM volumes are a whole different kettle of fish. I don't need to support them right now, but if taking them into account requires little extra effort, I wouldn't mind.

  • How portable? My laptop has its root partition on /dev/sd0a but there's no /dev/sd0 device (there is a /dev/sd0c...) – thrig Sep 8 '16 at 19:28
  • @don_crissti, /dev/sda1 and /dev/mmcblk0p1 are Linux-specific anyway. lsblk is relatively recent though. – Stéphane Chazelas Sep 8 '16 at 19:28
  • lsblk also uses the device node numbers to find the correct one, instead of just using the name. seems the simplest solution for Linux and util-linux would likely be always available anyway. – ilkkachu Sep 8 '16 at 19:36
  • 1
    @don_crissti lsblk -dpno pkname $devname passed all my tests! Perhaps you should add an answer. – Dmitry Grigoryev Sep 8 '16 at 19:37
  • @thrig Well yeah, I'd definitely expect the script to return /dev/sd0c in that case. Do the answers below work for you? – Dmitry Grigoryev Sep 9 '16 at 10:38
15

If you're on linux you could use lsblk (which is part of util-linux):

lsblk -no pkname /dev/sda1
  • 2
    My lsblk (util-linux:2.20.1, Ubuntu 14.04) does not have the pkname column, just kname. – heemayl Sep 8 '16 at 19:46
  • 3
    @heemayl - it was added only four years ago so not available on distros that use older releases... – don_crissti Sep 8 '16 at 19:49
  • $ lsblk -no pkname /dev/nvme0n1p3 returns 7 lines on my system. Yep, this partition is encrypted, and contains LVM, this is not a trivial situation. I don't know how you're supposed to reliably pickup the right line from a script. – elboulangero Oct 10 '18 at 4:14
15

If a device is a partition of another device then /sys/class/block/$dev will contain a file called partition (whose content is the partition number).

If that's the case, you can get the name of the parent device with:

basename "$(readlink -f "/sys/class/block/$dev/..")"

Or with zsh:

echo /sys/class/block/$dev(:A:h:t)

Example:

$ dev=sda1
$ basename "$(readlink -f "/sys/class/block/$dev/..")"
sda
$ dev=nbd0p1
$ basename "$(readlink -f "/sys/class/block/$dev/..")"
nbd0

LVM volumes are completely different, they are not partitions except in the special case where they are one contiguous linear mapping of a physical PV.

If you're in such a case, you can get the name of that PV with:

ls "/sys/class/block/$dev/slaves"

Where $dev is something like dm-2 (which you can obtain from "$(basename "$(readlink -f /dev/VG/LV)")").

  • I have accepted don_crissti's answer because I happen to have lsblk and the syntax is short, but I acknowledge that your answer is more generic and portable. Thanks! – Dmitry Grigoryev Sep 9 '16 at 10:21

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.