0

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 }
  • 2
    Why not parse ls? – Cyrus Feb 24 '18 at 2:37
  • 2
    Parsing the output from ls is a very bad idea. Is this homework?  Can you use stat? – G-Man Feb 24 '18 at 3:14
  • 1
    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 '18 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. – dave_thompson_085 Feb 24 '18 at 7:26
4

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}'
  • Why not parse ls? – Cyrus Feb 24 '18 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 '18 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.

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.