Скрипт не работает для рекурсивного прохода по каталогам

Скрипт не работает для рекурсивного прохода по каталогам

Поэтому я создаю скрипт, который рекурсивно подсчитывает размер всех файлов в текущем каталоге и всех файлов в подкаталогах:

#!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 "$?"

Однако при запуске скрипта я получаю следующий вывод:

/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 — это файл внутри каталога dir, и я не знаю, почему он создает эту проблему, хотя очевидно, что когда я выполняю команду ls -l для каталога:

 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 ~]$

Это показывает, что файл действительно существует.

Есть идеи?

решение1

Основная проблема в вашем коде (кроме использования не заключенных в кавычки расширений переменных и того, что выцикл по выходным даннымls(излишне) заключается в том, что вы не добавляете к имени файла, на котором вы работаете, префикс ls -lимени его каталога. У вас также возникнут трудности в сопоставлении выводимого размера с каталогом, размер которого это.

Вы также используете returnдля возврата размера из вашей функции. returnОператор должен использоваться для возврата статуса выхода функции (ноль — успех, не ноль — неудача, значения должны быть меньше 256).

Реализация функции оболочки:

#!/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}"

Это дало быочевидныйразмер всех каталогов. duдастдействительныйразмер, выделенный на диске. Разница в том, как будут подсчитываться разреженные файлы.

То же самое, но с использованием findдля генерации путей к каталогам для printdirsizeфункции (здесь извлечено и использовано как встроенный скрипт, вызываемый с помощью 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 {} +

Единственное отличие от рекурсивной функции заключается в том, что порядок каталогов в выводе может быть другим.

решение2

Если вам нужен только размер всех файлов в вашем каталоге, что du -sh *вам не подойдет?

Связанный контент