21

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.

5
  • 1
    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, 2016 at 19:28
  • @don_crissti, /dev/sda1 and /dev/mmcblk0p1 are Linux-specific anyway. lsblk is relatively recent though. Sep 8, 2016 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, 2016 at 19:36
  • 2
    @don_crissti lsblk -dpno pkname $devname passed all my tests! Perhaps you should add an answer. Sep 8, 2016 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? Sep 9, 2016 at 10:38

2 Answers 2

27

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

lsblk -no pkname /dev/sda1
4
  • 2
    My lsblk (util-linux:2.20.1, Ubuntu 14.04) does not have the pkname column, just kname.
    – heemayl
    Sep 8, 2016 at 19:46
  • 3
    @heemayl - it was added only four years ago so not available on distros that use older releases... Sep 8, 2016 at 19:49
  • 2
    $ 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. Oct 10, 2018 at 4:14
  • @elboulangero can you post what the seven lines look like?
    – simgineer
    Jan 18 at 23:23
21

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)")").

1
  • 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! Sep 9, 2016 at 10:21

You must log in to answer this question.

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