Abstract:
Portable, In one line and using printf:
awk '/MemTotal/{t=$2}; /MemFree/{f=$2}; END{printf("%d\n",(1-f/t)*100)}'
Only Shell (bash):
memused() { : # Print the (integer) value of % of free memory
local ret ref a t f
ret='MemTotal:[ \t]*([0-9]+)'; # Regex for Total memory.
ref='MemFree:[ \t]*([0-9]+)'; # Regex for Free memory.
a=$(</proc/meminfo) # Get meminfo in var (a).
[[ $a =~ $ret ]] && t="${BASH_REMATCH[1]}" # Get Total memory.
[[ $a =~ $ref ]] && f="${BASH_REMATCH[1]}" # Get Free memory.
printf '%s\n' "$(( 100 - 100*f/t )) %" # Print integer % value.
}
Description
The reason for the complaint of bc is that it is only getting one var.
To reproduce:
$ t=150 ; f='' ; bc <<< "scale=2; 100 - $f / $t * 100"
(standard_in) 1: syntax error
One way to avoid that error is to set a default value:
$ t=150; f=''; bc <<< "scale=2; 100 - ${f:-0} / ${t:-0} * 100"
100
The reason for only one value is that the read is getting the values in separate lines (in bash 4.4). A solution that works well for all bash versions is to use -d '':
$ read -d '' t f <<< "`grep -E 'Mem(Total|Free)' /proc/meminfo |awk '{print $2}'`"
$ echo "total=<$t> free=<$f>"
total=<1922764> free=<424360>
And that also works whether the command expansion is quoted (as it should be) "`grep … '`" or not.
But there is no reason to call grep, awk, bc and finally cut. One call to awk could do it all:
</proc/meminfo awk '/MemTotal/{t=$2}
/MemFree/ {f=$2}
END{
print( (1-f/t)*100 )
}
'
In one line and using printf:
awk '/MemTotal/{t=$2};/MemFree/{f=$2};END{printf("%d\n",(1-f/t)*100)}' </proc/meminfo
If you want something that works faster and only use the shell (albeit bash):
memused() { : # Print the (integer) value of % of free memory
local ret ref a t f
ret='MemTotal:[ \t]*([0-9]+)'; # Regex for Total memory.
ref='MemFree:[ \t]*([0-9]+)'; # Regex for Free memory.
a=$(</proc/meminfo) # Get meminfo in var (a).
[[ $a =~ $ret ]] && t="${BASH_REMATCH[1]}" # Get Total memory.
[[ $a =~ $ref ]] && f="${BASH_REMATCH[1]}" # Get Free memory.
printf '%s\n' "$(( 100 - 100*f/t )) %" # Print integer % value.
}