0

I'm trying to get a list of devices on my linux box from normal bash commands in a script. I've used the following however it isn't working. Ideally, I'd like to get all sd* and nvme devices into an array. This is what I have tried:

lsblk --nodeps | sed -n '/sd\.*/p'
lsblk --nodeps | sed '/(sd | nv)\.*/p'
lsblk --nodeps | sed -n 's/^([a-z0-9]+?).*/\1/'
lsblk --nodeps | sed -n '/^.*?/p'
lsblk --nodeps | sed '/^(.+?)\s*/p'
lsblk --nodeps | sed '/^(s.+?|n.+?)?)\s*/p'

This is the starting syntax:

$ lsblk --nodeps
NAME    MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda       8:0    0 119.2G  0 disk
sdb       8:16   1  57.8G  0 disk
nvme0n1 259:0    0 232.9G  0 disk

So I want to regex for sd* and nvme, without the trailing spaces.

Any insight appreciated how I can get drives into an array.

10
  • You realize you can get a list of block devices from /dev? You don't need lsblk for the job at all. Commented Jun 25, 2022 at 22:46
  • shopt -s nullglob; cd /dev; disks=( sd* nvme* ) and there you are, you get an array named disks with, in your case, three entries. Commented Jun 25, 2022 at 22:47
  • Or, to get easy-to-parse output from lsblk, you can do something like readarray -t disks < <(lsblk -nr --output NAME | egrep '^(sd|nvme)'). No reason to fight to parse a table when you can just ask for a format that's easier-to-parse than a table. Commented Jun 25, 2022 at 22:50
  • ...eh, going to migrate the above two comments into an answer. Commented Jun 25, 2022 at 22:51
  • I was under the impression that sed could parse and return items. Commented Jun 25, 2022 at 22:53

1 Answer 1

1

Making lsblk Output Easier To Parse

lsblk can be told to suppress a header line, and to emit only the specific pieces of data you care about -- in this case, device names.

If you have a listing with nothing but device names, grep is the easiest tool to use to parse them; but to add an additional rule (in this case, discarding partitions), awk comes into play.

Thus:

readarray -t disks < <(lsblk -dnr --output NAME | grep '^(sd|nvme)')

Filtering /dev/disk/by-id Yourself

For the stubborn, to show that it can be done:

shopt -s nullglob extglob
declare -A results=( )
devices=( /dev/disk/by-id/!(*-part*) )
for device in "${devices[@]}"; do
  target=$(readlink -f "$device")
  results[${target#/dev/}]=1
done
disks=( "${!results[@]}" )
declare -p disks # print the resulting array
Sign up to request clarification or add additional context in comments.

9 Comments

``` [Sat Jun 25 19:00:26 rich@server1 /dev] declare -p disks declare -a disks='([0]="nvme0" [1]="nvme0n1" [2]="sda" [3]="sda1" [4]="sda2" [5]="sdb" [6]="sdb1" [7]="sdb2")' [Sat Jun 25 19:00:26 rich@server1 /dev] echo $disks nvme0 ```
echo "${disks[@]}" to print all elements of the array -- when you echo $disks it prints only ${disks[0]}. (That's true for all arrays in bash; if you're accustomed to different behavior, you aren't really using arrays).
nvme0 nvme0n1 sda sda1 sda2 sdb sdb1 sdb2 Still has partitions.
Fair 'nuff. One could do more magic to distinguish dependent devices (devfs and sysfs let you do everything lsblk does yourself -- they're where it gets its data), but it's work.
The nvme drives not showing up, as the partitions have convoluted endings. declare -a disks='([0]="sda" [1]="sdb")'
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.