Количество файлов в каталогах в Unix с использованием рекурсивного подхода

Постановка задачи: перечислить количество файлов в каталоге. Примечание. Каталог может содержать либо подкаталог, либо файлы, но не оба вместе. Необходимо перечислить количество файлов в каталоге. Вот кусок кода.

#!/usr/bin/sh 
directory_navigate()
{   
    path=$1
    cd $path
    dir_count=`ls -l|grep '^d'|wc -l`
    if [ $dir_count -gt 0 ]
    then
        for dir in `ls`
        do
            sub_path="$path/$dir"
            directory_navigate $subpath
        done
    else    
        sub_path=`pwd`
        file_count $sub_path 
        return
    fi
}   

file_count ()
{
    path=$1
    cd $path
    count=`ls|wc -l`
    echo "Count of files in $path is $count"
    return
}

main()
{
    filepath=/var/prod/data/extract/tbill
    directory_navigate $filepath
    return 
}

main 

Это выдает следующую ошибку: слишком глубокая рекурсия


person user3004    schedule 19.12.2016    source источник
comment
Как насчет того, чтобы просто использовать find?   -  person Inian    schedule 19.12.2016


Ответы (1)


Используйте 1_ . В bash сделать

shopt -s globstar
count=0
for name in /basefolder/**
do
[ -f "$name" ] && (( count++ ))
done
echo "Total files : $count"

Более простой подход, предложенный в комментарии,

find /basefolder/ -type f -printfc | wc -c

Здесь загвоздка в том, что нам не нужно парсить (и не парсим, мы просто хотим посчитать) файлы, если нам требуется парсить файлы для более сложных требований, то ниже приведены некоторые причины не использовать find.

  • Использование find требует, чтобы каждый файл был разделен нулем (т. е. использовалось -print0).
  • Кроме того, вам нужно использовать комбинацию while - read -r -d ' ' для разбора каждого файла.
  • Короче говоря, не стоит усилий.

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

#!/bin/bash
shopt -s globstar
for name in ~/Documents/so/**
do
if [ -d "$name" ]
then
  count="$(find "$name" -type f -printf c | wc -c)"
  echo "Total files in $name : $count"
fi
done
person sjsam    schedule 19.12.2016
comment
В качестве примечания, globstar доступен только начиная с bash 4.0. Некоторые ОС, такие как MacOS, не будут иметь его по умолчанию, и им потребуется обновить свою оболочку. - person Aserre; 19.12.2016
comment
@Aserre: Хорошая заметка, я знаю об этом. Оп упомянул unix, о котором идет речь, так что, надеюсь, у него есть версия bash › 4.0. - person sjsam; 19.12.2016
comment
MacOS основан на Unix :) - person Aserre; 19.12.2016
comment
Как насчет использования find . -type f -printf c | wc -c? Не требует больших усилий - person user000001; 19.12.2016
comment
@user000001 user000001: это не касается нестандартных файлов, таких как AnewlineB. На самом деле эти файлы редки, но они существуют на некоторых машинах. - person sjsam; 19.12.2016
comment
@sjsam: Да, он справится. Он печатает один символ для каждого файла независимо от имени файла. Конечно, есть проблема, что некоторые реализации find могут не иметь опции printf... - person user000001; 19.12.2016
comment
@Aserre: Опять же, я согласен, но пользователи Mac обычно отмечают Mac в вопросах. - person sjsam; 19.12.2016
comment
@ user000001: Не будет. find в отличие от ls не будет добавлять случайные символы вместо новых строк, действительно, это одна из особенностей find. - person sjsam; 19.12.2016
comment
@sjsam: Звучит очень странно. Опубликуйте вывод find . -type f -printf c на своей консоли. Вы должны увидеть символ c, напечатанный несколько раз, независимо от имен файлов, содержащихся в текущем каталоге. - person user000001; 19.12.2016
comment
@user000001 user000001: Извините, я проглядел -printf c в вашем комментарии. Да, он делает то, что должен делать.. :) - person sjsam; 19.12.2016
comment
привет, здесь требуется найти количество файлов в каталоге. Таким образом, функция find не соответствует этому требованию, а также не работает опция printf. - person user3004; 20.12.2016