-1

I have an .img file from which I would like to extract 2 values derived with fdisk, as strings in 2 variables.

fdisk -l /home/documents/image-of-sd-card.img
Disk /home/documents/image-of-sd-card.img: 14,84 GiB, 15931539456 bytes, 31116288 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc680d152

Device                                    Boot  Start      End  Sectors  Size Id Type
/home/documents/image-of-sd-card.img1        8192   655359   647168  316M  c W95 FAT32 (LBA)
/home/documents/image-of-sd-card.img2      655360 31115263 30459904 14,5G 83 Linux

The values I would need are the last unit from "Sector size" (512) and the End size of the second partition (31115263). How to achieve that? I would prefer a Bash based solution so that I could integrate this into an existing Shell script.

As an absolute beginner in Linux I just played around with some greb commands but to no avail.

Community
  • 1
  • 1
TimZed
  • 11
  • 1
  • 4
  • 4
    What was your attempt? Do you now grep, awk, etc ? – JRichardsz Aug 19 '23 at 13:27
  • What have you tried so far? StackOverflow expects you to [try to solve your own problem first](//meta.stackoverflow.com/q/261592), as your attempts help us to better understand what you want. Please edit the question to show what you've tried, and show a specific roadblock you're running into with a [mcve]. For more information, please see [ask]. – Toby Speight Aug 19 '23 at 19:11

4 Answers4

1

Here a steps by step explanation to help you in your bash learning

raw_content=$(fdisk -l /home/documents/image-of-sd-card.img)

sector_size=
second_partition_size=
while read i 
do 

    if [[ "$i" == "Sector size"* ]]; then
        echo ">>>>$i" 
        echo "$i" | cut -d ' ' -f 7
        sector_size=$(echo "$i" | cut -d ' ' -f 7)
    elif [[ "$i" == "/home/documents/image-of-sd-card.img2"* ]]; then
        echo ">>>>$i" 
        echo "$i" | awk -F' ' '{ print $3 }'
        second_partition_size=$(echo "$i" | awk -F' ' '{ print $3 }')        
    fi

done <<< "$raw_content"

echo -e "\nResults:"

echo "sector_size: $sector_size"
echo "second_partition_size: $second_partition_size"

Output:

Explanation

  • raw_content=$(...) will save all the output in a var
  • while read i ... done <<< "$raw_content" will iterate line by line and set the value in i var
  • if [[ "$i" == "Sector size"* ]]; will ask if string starts with ...
  • echo "$i" | cut -d ' ' -f 7 will split by one space and get you the desired column
  • echo "$i" | awk -F' ' '{ print $3 }' will split by several spaces and get you the desired column

Recommended lectures

JRichardsz
  • 14,356
  • 6
  • 59
  • 94
0

With fdisk installed, you usually also have sfdisk available, which is a "script-oriented" fdisk. You can give it the --json (or -J) option to output the information in a more structured format (try out just entering sfdisk -J /path/to/device to see the entire output), which can then be processed by a JSON processor (jq for example) that can precisely extract what you need. Use "$(...)" to capture the output, and assign it to a variable.

sectorsize="$(sfdisk -J /path/to/device | jq '.partitiontable.sectorsize')"
part2size="$(sfdisk -J /path/to/device | jq '.partitiontable.partitions[1].size')"

With more variables, you might want to combine the calls. Here's one example:

{ read sectorsize; read part2size; } < <(
  sfdisk -J /path/to/device | jq '.partitiontable | .sectorsize, .partitions[1].size'
)
pmf
  • 24,478
  • 2
  • 22
  • 31
0

This can be used for extracting the Sector size

 size=$(fdisk -l /home/documents/image-of-sd-card.img |awk
'/^Sector/ {print $4}')

Similar pattern matching can be used to extract the second required value.

second_end=$(fdisk -l /home/documents/image-of-sd-card.img |awk
 '/^img2/ {print $3}')
raghu
  • 335
  • 4
  • 11
0

It might be better if you find some script-oriented tool like sfdisk, and it will be safer.

Otherwise, this can be solved combination of grep/sed/owk or even by pure bash.

fdisk .... > tmpx;
A="$(
    sed -n '\|Sector size (logical/physical)|{ s|.*/ *||; s| *bytes *||; p };'  tmpx
    )"
B="$(  awk '/sd-card.img2/{print $3}'  tmpx  )"

echo "The-results---$A---$B---"

The-results---512---31115263---

Explanations for sed command: -n says do-not-print to sed, while p is the print command. sed program starts by so called address \| <regular expression> | which works as a selector. Following block { ... } is executed for the mathing lines and contains s| <what> | <bywhat>| where we request to replace any <what> = .*/ * (meaning anychar(.) repeated-arbitrarily(*) followed-by-slash(/) followed-by space( ) repeated-arbitrarily(*)). We replace <what> by the empty string. Then we replace (s|...|..|) <what> = "bytes" together with any spaces. Finally we print (p) the result.

Explanation for awk command: For the lines matching the address /..../ command print executed to print third $3 word on the line.

--

Pure bash solution:

A="error"; B="error"; 
while read a b c d e f g h  ; do 
    [ "$a,$b,$c,,$e,$f" == "Sector,size,(logical/physical):,,bytes,/" ] && A="$g";
    [[ "$a" == *sd-card.img2 ]] && B="$c"; 
done < tmpx;
echo "The-results---$A---$B---"

Note: [ ... == ... ] is different from [[ ... == ... ]].

minorChaos
  • 101
  • 7