6

How do I modify the df -h command to add the results of following command (in other words, add them all together and return the result)?

$ df -h | awk '{print $2}'
Size
5.8G
64G
93M
3.9G
12G
108G
16G
134G
3.7T
3.7T
6.0T
aliceinpalth
  • 1,613
tester787
  • 449

3 Answers3

11

GNU df can do the totalling by itself, and recent versions (at least since 8.21, not sure about older versions) let you select the fields to output, so:

$ df -h --output=size --total
 Size
 971M
 200M
  18G
 997M
 5.0M
 997M
  82M
  84M
  84M
 200M
  22G
$ df -h --output=size --total | awk 'END {print $1}'
22G

From man df:

--output[=FIELD_LIST]
      use the output format defined by FIELD_LIST, or print all fields
      if FIELD_LIST is omitted.
--total
      elide  all entries insignificant to available space, and produce
      a grand total
Olorin
  • 4,656
7

The human-readable formatting of the numbers gets in the way, so you need to have consistent output first. Portably, you can use -P option to output in blocks of 1024

df -P | awk 'NR>2{sum+=$2}END{print sum}'

If you use GNU df you can specify --blocksize option:

df --block-size=1  | awk 'NR>2{sum+=$2}END{print sum}'

NR>2 portion is to avoid dealing with the Size header line. As for formatting data back into human readable format, if you are on Linux you can use numfmt tool, otherwise - implement converter in awk. See the related answer.

Note also that df outputs sizes for all filesystems, including virtual filesystems such as udev and tmpfs. You might consider filtering those out if you want the actual physical disks only. So if we consider only filesystems that have a device file represented in /dev/ filesystem, you could probably use something like this:

df -P | awk 'NR>2 && /^\/dev\//{sum+=$2}END{print sum}'

With GNU df you could consider using --local flag as well, to ignore remove filesystems.

  • 1
    +1. with GNU df you can also use -x to exclude some filesystems. e.g. -x tmpfs -x devtmpfs – cas Feb 16 '18 at 00:00
0

In some cases (ie btrfs) a filesystem appears multiple times in df. So a better sulution is

 df | awk '/dev\/sd/ {sums[$1]=$3} END {for (i in sums) tot += sums[i]; print tot}' | numfmt --to=iec
jtsagata
  • 111