3

I'm new to bash and I need to do a little script to sum all file sizes, excluding subdirectories. My first idea was to keep the columns when you do ls -l. I cannot use grep, du or other advanced commands I've seen around here.

$9 corresponds to the 9th column where the name is shown.

$5 is the size of the file.

ls -l | awk '{if(-f $9) { total +=$5 } }; END { print total }
4
  • 2
    Why not parse ls?
    – Cyrus
    Feb 24, 2018 at 2:37
  • 2
    Parsing the output from ls is a very bad idea. Is this homework?  Can you use stat? Feb 24, 2018 at 3:14
  • 2
    why can't you use du? is this homework? (homework is OK here, but it's best to mention that it is because most people here prefer to give hints and point you in the right direction rather than give a complete answer if it's for homework).
    – cas
    Feb 24, 2018 at 4:26
  • 1
    Column 9 is not the filename if the filename contains whitespace, as is allowed and fairly common. In addition to the badness of using ls, tests like -f name work in the standard-and-traditional test-aka-[ utility, the similar ksh-bash-etc-only [[ builtin, and perl, but not awk. Feb 24, 2018 at 7:26

5 Answers 5

7

With GNU find and awk:

find . -maxdepth 1 -type f -printf "%s\n" | awk '{sum+=$1} END{print sum+0}'

Output is file size in bytes.  The final statement is print sum+0 rather than just print sum to handle the case where there are no files (i.e., to correctly print 0 in that case).  This is an alternative to doing BEGIN {sum=0}.

1

Using wc:

wc -c * 2> /dev/null

If all that's needed is the total, do:

wc -c * 2> /dev/null | tail -1
1

If you're looking for a bash-centric, shell-script way to do it, here's a shell loop that gathers all of the files (dot-files included), then uses the GNU coreutils stat utility to print their size into a summation variable.

shopt -s dotglob
sum=0
for f in *
do 
  [[ -f "$f" && ! -h "$f" ]] || continue
  sum=$(( sum + $(stat -c "%s" "$f") ))
done
echo $sum

Bash considers symlinks to be "regular files", so we must skip them with the -h test.

0

We can use below command too

find . -maxdepth 1 -type f -exec ls -ltr {} \;| awk 'BEGIN{sum=0} {sum=sum + $5} END {print sum}'
2
  • Why not parse ls?
    – Cyrus
    Feb 24, 2018 at 11:46
  • What benefit is there to doing a -tr in the ls when all you're doing is counting bytes one file at a time? It is indeed dangerous to parse ls, although you should be safe(r) counting only the file size.
    – Jeff Schaller
    Feb 25, 2018 at 2:02
0

As it was a very basic exercise, teacher demanded the exercises using basic commands that requiere a little bit more development and can be replaced by more powerful commands like find or stat later on. But I got the answer and it was this:

dir=$1
if [ ! -d $dir ]
then 
   exit 1
else

sum=0
cd $dir

(ls -l $dir) > fitxers.txt

C=($(awk '{print $5}' fitxers.txt))

len=${#C[*]}

i=0

while [ $i -lt $len ]
do 
    for element in $(ls $dir)
    do
        if [ -f $element ]
            then
            let "sum = $sum + ${C[$i]}"
            fi 
        (( i++ ))
    done
done
echo $sum
rm -r fitxers.txt
exit 0
fi

Hope it's a little bit helpfull for other beginners.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .