Monday, May 13, 2024
1
rated 0 times [  1] [ 0]  / answers: 1 / hits: 591  / 2 Years ago, mon, june 13, 2022, 9:32:22

I want to write simple linux script which will display what are the real size of installed hard drive. If there is 128GB SSD, lsblk shows less than 128. I need to check the real size of memory and print it like this: 128GB installed = script gives output


128

If there are two hard drives installed, it gives output


128/512

It should work on both sata and nvme drives


More From » command-line

 Answers
0

It requires sudo to use but it works:


sudo lshw | grep -Pzo "*-(disk|namespace)(
.*)+?s+size:.*?(Kd+w+" | tr "0" "
" | paste -sd/

It gives the output like this:


1TB/750GB

Otherwise you wouldn't know if it was TB/GB/MB so that's why I kept those.


EDIT: I noticed an .* in the regex wasn't needed. The command above has been updated.


Explanation:


sudo lshw: well... list the hardware. We need sudo to see the drives in the system. This will be our source of info.


grep -Pzo: we're going to use regex to get the required info


-P = activate perl regex
-z = treat everything as one long line; this is required because we're going to use regex over multiple lines
-o = instead of showing the output and marking the result red, just show the result

regex (tip: remove the -o (a.k.a -Pz) and add the regexes below one by one to see what happens step by step; the red text is what the regex matched, so you can see step by step how we're getting closer to the desired result and what every step changes to the output):


*-(disk|namespace) = Find all text that is "*-disk" or "*-namespace". We need to escape (= ) the "*" because in regex it means zero or more, but we don't want that, we want to search for a literal "*".
(
.*)+ = Keep adding (the "+" = one or more) lines ("
" = go to the next line; ".*" = everything on that line) to the matched text; you'll see that now everything under the first match of "*-(disk|namespace)" is red.
?s+size: = we keep adding lines until we come across the first ("?" = non-greedy a.k.a. the first match instead of the last match) match of one or more whitespaces (= "s+"; "s" is whitespace (tab, space, etc.); "+" is one or more) and then "size:"; you'll see that were coming closer to the desired number in the output.
.* = match the rest of that line,
?( = until the first match (= ?) of a "(", which we need to escape because it is used in regex (you can see it being used in the first part of the regex here).
Kd+w+ = match a number (= d) one or more times (= "+") and after that a word character (= w) one or more times (= "+"). We now have the desired text in the match, but we don't want all the matched text before that in the output, so we put a "K" before the desired text to remove the matched text before the "K" from the output. It is still required to match, it just isn't included in the output. This makes all the regex before it a positive lookbehind (look it up; "positive lookbehind perl regex") with regex capabilities.

tr "0" "
"
:
You'll see that we have the desired text matched and nothing more or less.
When we add the -o again, you'll see that the results are displayed in a weird way (all after each other).
That is because they are seperated with a null character (= 0) which you can't see, instead of a newline. This is an artifact of the "-z" option of grep.
To show them in a normal list, were going to replace the null characters with a newline using tr.


paste -sd/: now that we have the results in a list, we can use the paste command to put them after each other, using a "/" as a devider.


[#1310] Wednesday, June 15, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
torlim

Total Points: 408
Total Questions: 113
Total Answers: 110

Location: Estonia
Member since Wed, May 27, 2020
4 Years ago
torlim questions
;