0

So I'm creating a script that counts the size of all the files in the current directory and all the files in the subdirectories recursively:

#!bin/bash

Count () {
    size=0
    items=`ls "${1}/"`
    for item in $items
            do
            if [ ! -d $item ]
            then
                    cursize=`ls -l $item | awk '{ print $6 }'`
                    size=$[$size+$cursize]
            else
                    echo "$1/$item"
                    Count $1/$item
                    size=$[$size+$?]
            fi
    done
    echo "Done"
    return $size
}

Count ~

echo "$?"

However when I run the script I get the following output:

/home/161161/backup
Done
/home/161161/dir
ls: xoe1.txt: No such file or directory
script.sh: line 11: 28+: syntax error: operand expected (error token is "+")
1

xoe1.txt is a file inside the dir directory and I don't know why it makes this problem when clearly when I do an ls -l on the directory:

 ls -l dir
total 4
-rw-r--r-- 1 161161 domain users 23 Jun  2 22:55 test1.txt
-rw-r--r-- 1 161161 domain users  0 Jun  2 15:27 test2.txt
-rw-r--r-- 1 161161 domain users  0 Jun  2 15:27 test3.txt
-rw-r--r-- 1 161161 domain users  0 Jun  2 22:42 xoe1.txt <--
-rw-r--r-- 1 161161 domain users  0 Jun  2 22:42 xor1.txt
[161161@os ~]$

It shows that file does in fact exits.

Any ideas?

2 Answers2

1

The main issue in your code (apart from using unquoted variable expansions throughout and that you're looping over the output of ls needlessly) is that you don't prefix the filename that you run ls -l on with its directory name. You would also have difficulties in pairing up the size output with the directory that this is the size of.

You are also using return to return the size from your function. The return statement should be used to return the exit status of the function (zero is success, non-zero is failure, values should be less than 256).

Shell function implementation:

#!/bin/bash

# Uses stat to get the total size in bytes of all files in the directory
# given on the function's command line. Assumes Linux "stat".
printdirsize () {
    local dir="$1"
    local sum=0

    shopt -s dotglob nullglob

    for filename in "$dir"/*; do
        [ ! -f "$filename" ] && continue  # skip non-regular files
        size=$( stat -c %s "$filename" )
        sum=$(( sum + size ))
    done

    printf 'Directory=%s\nSize=%d\n' "$dir" "$sum"
}

# Walks the directory tree from the given directory, calls printdirsize
# (above) and then descends into the subdirectories recursively.
dirwalker () {
    local dir="$1"

    printdirsize "$dir"

    shopt -s dotglob nullglob

    for filename in "$dir"/*; do
        [ ! -d "$filename" ] && continue  # skip non-directories
        dirwalker "$filename"
    done
}

# Start in the directory given on the command line, or use $HOME if
# nothing was given
dirwalker "${1:-$HOME}"

This would give the apparent size of all directories. du would give the actual size allocated on disk. The difference is in how sparse files would be counted.

The same thing, but using find to generate the directory pathnames for the printdirsize function (here extracted and used as an inline script called by find):

#!/bin/sh

find "${1:-$HOME}" -type d -exec bash -O dotglob -O nullglob -c '
    for dir do
        sum=0
        for filename in "$dir"/*; do
            [ ! -f "$filename" ] && continue  # skip non-regular files
            size=$( stat -c %s "$filename" )
            sum=$(( sum + size ))
        done
        printf "Directory=%s\nSize=%d\n" "$dir" "$sum"
    done' bash {} +

The only difference from the recursive function is that the order of the directories in the output may be different.

Kusalananda
  • 333,661
0

If you just want the size of all the files in your directory would du -sh * not work for you?

Joe M
  • 876
  • Yes you can but this is for an assignment and they specifically want to go through the folders recursively and through the files one by one and count all of their sizes. – David Mathers Jun 02 '18 at 23:21