I am trying to store Available and Total Memory into variables in a script file as follows,

read -r Available Total <<EOT
$(free -m | awk '/^Mem/{print $7; print $2;}')

$ echo $Total

$ echo $Available

But I am unable to store the variable $Total.

But when I do:

$ read Available Total <<EOT
$(echo $(free -m | awk '/^Mem/{print $7; print $2;}'))

$ echo $Available
$ echo $Total

It works. But shellcheck gives me following suggestion:

Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]

Why the forst example didn't work? and Why the second one works?


That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.

Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:

$ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )

Or use a process substitution:

$ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )

If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.

echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.

| improve this answer | |
  • 1
    Process Substitution would work here as well. – glenn jackman Jan 13 '19 at 13:15
  • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this? – Nikhil Jan 13 '19 at 16:47
  • 2
    @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.) – ilkkachu Jan 13 '19 at 17:10
  • 1
    Yes, read reads stdin, so you need a redirection. – glenn jackman Jan 13 '19 at 18:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.