2

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 '18 at 7:30
  • 1
    @msp9011, du will calculate also subdirectories – Romeo Ninov Nov 21 '18 at 7:39
  • 1
    @RomeoNinov here we are checking only files...du -b /etc/*.conf – msp9011 Nov 21 '18 at 8:42
  • @msp9011 Not if there is a directory matching the pattern. It's unlikely but not impossible. – BlackJack Nov 21 '18 at 17:55
  • @msp9011 due to block sizes, etc, disk usage is not the same as total file size. – OrangeDog Nov 22 '18 at 11:45
2

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 '18 at 7:25
  • 4
    Don't use grep or cut on stat output. stat has format flags (%s) for this – ohno Nov 21 '18 at 10:20
  • 5
    Also, 'Size' is likely to assume an English or "C " locale. – xenoid Nov 21 '18 at 13:43
13

Also something like can do the work (with awk)

stat -c "%s" /etc/*.conf|awk '{s+=$1} END {print s}'
  • 1
    It requires you know a little AWK syntax (which, on the whole, is graciously C-like), but AWK is good at "sum up this column in this delimited file and print the total for me." Sometimes I forget. :) – TheDudeAbides Dec 19 '18 at 19:21
12
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 '18 at 23:20
  • 2
    @TheDudeAbides, all those things are true about awk. And it use one process less. And IMO is much more readable – Romeo Ninov Nov 22 '18 at 10:29
10

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 +
7

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 '18 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 '18 at 17:04
  • @Ruslan The awk line also strips off the total – Izkata Nov 21 '18 at 18:09
  • @Izkata oh, indeed, didn't notice this bit. – Ruslan Nov 21 '18 at 18:49

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.