# Using bc to total numbers in a file



## balanga (Apr 22, 2021)

Does anyone know if it's possible to use bc() to total the numbers in a file, ie something which just has a number on every line, eg:-

```
27
53
77
143
```


----------



## VladiBG (Apr 22, 2021)

`awk '{ sum += $1 } END { print sum }' myfile.txt`

awk(1)



> Add up first column, print sum and average:
> 
> { s += $1 }
> END { print "sum is", s, " average is", s/NR }



`awk '{ s += $1 } END { print "sum is", s, " average is", s/NR }' myfile.txt`


----------



## balanga (Apr 22, 2021)

Thanks, not familiar with awk().... Would it be possible add up a mix of MB and KB?


----------



## covacat (Apr 22, 2021)

awk is the correct solution, but 


echo $(cat file.txt)|tr ' ' +|bc


----------



## aragats (Apr 22, 2021)

balanga said:


> Would it be possible add up a mix of MB and KB?


Probably not a perfect solution (I always use sed(), not awk() (-; ):
	
	



```
sed 's/[^0-9]*\([0-9]*\)[kK][bB]*.*/\1\*1024/; s/[^0-9]*\([0-9]*\)[mM][bB]*.*/\1\*1024^2/' my_file | bc | echo 0 `sed 's/^/+/'` | bc
```
However, to avoid an X-Y problem you should tell us more details on your file. In the OP you mentioned only numbers.


----------



## balanga (Apr 22, 2021)

I originally thought the denominations (is that the right word) would be the same but they are a mix:-

```
8KB
795KB
164KB
55KB
55KB
94.50MB
```

I've since come across* numfmt *which is in GNU's coreutils, but is missing from FreeBSD's version of this.


----------



## balanga (Apr 22, 2021)

aragats said:


> Probably not a perfect solution (I always use sed(), not awk() (-; ):
> 
> 
> 
> ...


I like using sed(), although not clever enough for scripts like that...

When I ran this it produced 


> bc: stdin:1: illegal character: : unexpected
> bc: stdin:1: illegal character: : unexpected


I just pasted it straight in from your post.


----------



## aragats (Apr 22, 2021)

If your lines start with a digit and may contain a decimal point, the script can be improved:
	
	



```
sed 's/^\([0-9\.]*\)[kK][bB]*.*/\1\*1024/; s/^\([0-9\.]*\)[mM][bB]*.*/\1\*1024^2/' num | bc | echo 0 `sed 's/^/+/'` | bc
```


----------



## VladiBG (Apr 22, 2021)

```
awk ' { s=substr($1,length($1)-1); if  (s=="GB") $1=( $1 * 1024 * 1024 ); else if (s=="MB") $1=( $1 * 1024 ); else if (s=="KB") $1= ( $1 * 1); sum += $1 } END { print sum/1024 "MB" }' myfile.txt
```


----------



## covacat (Apr 22, 2021)

improvement of aragats' version
sed -e 's/[^0-9]*\([0-9]*\)[kK][bB]*.*/\1\*1024/; s/[^0-9]*\([0-9]*\)[mM][bB]*.*/\1\*1024^2/; s/$/+\\/' -e '$s/+\\$//' file.txt |bc


----------



## ralphbsz (Apr 22, 2021)

When your input file says "MB", does that mean 1.000.000 bytes or 1.048.576 bytes?


----------



## Jose (Apr 22, 2021)

If you're parsing the output of du(1) keep in mind that utility will already give you a total with the `-c` option. Also, you won't have to worry about KB and MB suffixes if you don't use the `-h` option, and look at the `-k` option.

Edit: You might also find something like sysutils/jdiskreport useful.


----------



## balanga (Apr 22, 2021)

ralphbsz said:


> When your input file says "MB", does that mean 1.000.000 bytes or 1.048.576 bytes?


It's a usage report from my ISP. My allowance is 10GB, so I would guess it's 1.000.000 bytes.


----------



## bobmc (Apr 22, 2021)

balanga said:


> It's a usage report from my ISP. My allowance is 10GB, so I would guess it's 1.000.000 bytes.


A legacy spinning disk has 512 byte sectors so your allowance is probably an even multiple of that.


----------

