jamefane
jamefane

Reputation: 65

Bash - Extract kpartx output to variables

I want to extract the output off the kpartx tool:

add map loop18p1 (253:0): 0 1048576 linear 7:18 2048
add map loop18p2 (253:1): 0 1046528 linear 7:18 1050624

and then save loop18p1 and loop18p2 to $a and $b.

kpartx="$(sudo kpartx -av $IMAGE_FILE)"
read PART_FAT32 PART_NTFS <<<$(grep -o 'loop.p.' <<<"$kpartx")
a=/dev/mapper/$PART_FAT32
b=/dev/mapper/$PART_NTFS

echo $a
echo $b

but somehow it doesn't seem to work, I always get empty variables:

/dev/mapper/
/dev/mapper/

Kind regards,

jamefane

Upvotes: 2

Views: 835

Answers (3)

alecxs
alecxs

Reputation: 741

if you prefer a more generic way you may use dynamic variables for device letters. Notes: stderr is also redirected to grep in case kpartx can not map. declaration of array depends on shell.

# dynamic variable list for device letters
declare -a DEV=({a..z})

# assign kpartx results to device letters
for PART in $(sudo kpartx -av "$IMAGE_FILE" 2>&1 | grep -owE '(loop[0-9]+p[0-9]+)')
  do
    eval ${DEV[${i:-0}]}=/dev/mapper/$PART
    i=$((${i:-0}+1))
done

echo $a
echo $b

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295687

loop.p. doesn't match either loop18p1 or loop18p2. At minimum, you'd need to fix the grep to be something like grep -E -o 'loop[[:digit:]]+p[[:digit:]]+' (+ being a "one-or-more" modifier; so [[:digit:]]+ matches one-or-more digits in POSIX ERE, which is the syntax that grep -E enables).

Better than that, though, is to be aware of the syntax of the content you're reading, rather than just trying to blind-match content.

{
  read -r _ _ part_fat32 _  # first line:  read third word into part_fat32
  read -r _ _ part_ntfs _   # second line: read third word into part_ntfs
} < <(sudo kpartx -av "$IMAGE_FILE")
a="/dev/mapper/$part_fat32"
b="/dev/mapper/$part_ntfs"

Upvotes: 0

larsks
larsks

Reputation: 312370

I was going to keep working on this, but Charles Duffy swooped in and pretty much said the same thing via the comments, so I'll just leave this here for posterity. My goal was to walk through the process of diagnosing the problem.

Let's walk through your code. I'll use this image for my tests.

You start with this:

kpartx="$(sudo kpartx -av $IMAGE_FILE)"

On my system, that means:

$ IMAGE_FILE=2018-11-13-raspbian-stretch-lite.img
$ kpartx="$(sudo kpartx -av $IMAGE_FILE)"
$ echo "$kpartx"
loop3p1 : 0 89854 /dev/loop3 8192
loop3p2 : 0 3547136 /dev/loop3 98304

Your output may look different, but that should be sufficient for us to test out the remainder of the code.

Next you attempt to extract the device names from the $kpartx variable using a nested <<< expression:

$ read PART_FAT32 PART_NTFS <<<$(grep -o 'loop.p.' <<<"$kpartx")

This gets me:

$ echo $PART_FAT32
loop3p1
$ echo $PART_NTFS

In other words, $PART_NTFS is empty. That's because read only operates on a single line, and your grep command outputs multiple lines. The result of grep -o 'loop.p.' <<<"$kpartx" is:

$ grep -o 'loop.p.' <<<"$kpartx"
loop3p1
loop3p2

So you need to refactor how you're extracting those values.

Upvotes: 1

Related Questions