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.
CodePudding user response:
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