I want to add and echo the sum of several files using shell script. How do I start? I have a list of them like that:

$ stat /etc/*.conf | grep Size | cut -f4 -d' '
123
456
789
101112
  • 5
    you don't we simply use du? – msp9011 Nov 21 at 7:30
  • 1
    @msp9011, du will calculate also subdirectories – Romeo Ninov Nov 21 at 7:39
  • 1
    @RomeoNinov here we are checking only files...du -b /etc/*.conf – msp9011 Nov 21 at 8:42
  • @msp9011 Not if there is a directory matching the pattern. It's unlikely but not impossible. – BlackJack Nov 21 at 17:55
  • @msp9011 due to block sizes, etc, disk usage is not the same as total file size. – OrangeDog Nov 22 at 11:45
up vote 2 down vote accepted

You can do this …

total=0
for s in $(stat /etc/*.conf | grep Size | cut -f4 -d' '); do 
    total=$(expr $total + $s)
done
  • Thanks! and if I want to output it in a file I do: echo total > my_file.txt, right? And what if I want to output the errors too what do I do then? – C. Cristi Nov 21 at 7:25
  • 4
    Don't use grep or cut on stat output. stat has format flags (%s) for this – ohno Nov 21 at 10:20
  • 5
    Also, 'Size' is likely to assume an English or "C " locale. – xenoid Nov 21 at 13:43
stat -c "%s" /etc/*.conf|paste -sd+|bc -l
  • Although effectively the same as @xenoid's solution, I prefer this because 1) less rigamarole with format strings and remembering to append the final "0"; and 2) while it costs a process, it hews closer to the "one thing well" philosophy. It's also a useful use of the (perhaps underappreciated) paste utility that can be applied to a larger class of problems: separating a bunch of stuff with a delimiter. Another example is "unwrapping" (removing the line breaks from) a text file: paste -sd$' ' inputfile. – TheDudeAbides Nov 21 at 23:20
  • 1
    @TheDudeAbides, all those things are true about awk. And it use one process less. And IMO is much more readable – Romeo Ninov Nov 22 at 10:29

Also something like can do the work (with awk)

stat -c "%s" /etc/*.conf|awk '{s+=$1} END {print s}'

With bc

{ stat -c '%s+\' /etc/*.conf ; echo 0 ; } | bc
  • The stat format adds a + sign and a continuation character after each size
  • a 0 is appended at the end to close the dangling final +

The most straightforward way is to use du -bc:

$ du -bc /etc/*.conf
5139    /etc/man_db.conf
393     /etc/nsswitch.conf
5532    total

If you need to extract only the number of bytes, pipe the output to awk:

$ du -bc /etc/*.conf | awk 'END { print $1 }'
5532
  • Hope ... OP doesn't require the grand total size of all files... – msp9011 Nov 21 at 8:55
  • 1
    Also note that this gives disk usage, not apparent sizes of the files. --apparent-size option may be needed to use apparent sizes. – Ruslan Nov 21 at 17:04
  • @Ruslan The awk line also strips off the total – Izkata Nov 21 at 18:09
  • @Izkata oh, indeed, didn't notice this bit. – Ruslan Nov 21 at 18:49

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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