Количество файлов в каждой подкаталоги

22

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

Например , в каталоге /tmpтам dir1, dir2... Я хотел бы видеть:

`dir1` : x files 
`dir2` : x files ...
jldupont
источник

Ответы:

33

Предполагая, что вам нужно только рекурсивное количество файлов, а не каталогов и других типов, что-то вроде этого должно работать:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done
Тор
источник
Кроме того, я получаю «find: warning: вы указали опцию -maxdepth после не-аргумента аргумента -type, но опции не позиционные (-maxdepth влияет на тесты, указанные до него, а также на те, которые указаны после него). Пожалуйста, укажите опции перед другими аргументами. "
Jldupont
2
Оба ответа, приведенные до сих пор, дадут неправильные результаты в маловероятном случае, когда есть файлы, имена которых включают символы новой строки. Вы можете справиться с этим find... -print0 | xargs -0....
Скотт
@jldupont: переместите аргументы глубины до ´-типа d´, я отредактировал ответ.
Тор
Да, и позвольте мне добавить информацию, что это отличное решение не будет принимать никаких внешних переменных и, следовательно, будет работать с bash alias!!
syntaxerror
быстро и по трубам sort -rn -k 2,2 -t$':'вы получите список DESC
Andre Figueiredo
14

Эта задача настолько очаровала меня, что я сам хотел найти решение. Это даже не займет цикл, и МОЖЕТ быть быстрее в скорости выполнения. Излишне говорить, что усилия Тора очень помогли мне понять вещи в деталях.

Так вот мой

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

По какой-то причине это выглядит скромно, потому что это намного мощнее, чем кажется. :-)

Однако, если вы намереваетесь включить это в свой .bash_aliasesфайл, он должен выглядеть так:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

Обратите внимание на очень сложную обработку вложенных одинарных кавычек. И нет, нельзя использовать двойные кавычки для sh -cаргумента.

ошибка синтаксиса
источник
Это медленнее, так как он вызывает / bin / sh для каждого каталога. Вы можете проверить это с strace -fc script. Ваша версия делает примерно на 70% больше системных вызовов. +1 для более короткого кода :-)
Тор
1
вдохновленный этим; отсортировано по кол-ву файлов:find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
mnagel
7
find . -type f | cut -d"/" -f2 | uniq -c

Перечисляет папки и файлы в текущей папке с количеством файлов, найденных ниже. Быстрое и полезное ИМО. (файлы отображаются с количеством 1).

нет, спасибо
источник
1
Как насчет небольшого объяснения того, как это работает? :)
C0deDaedalus
1
офигенно, спасибо! Вы можете добавить, | sort -rnчтобы отсортировать подкаталоги по количеству файлов.
Деннис Голомазов
1

Использование find - определенно хороший способ, если вы хотите считать рекурсивно, но если вы просто хотите подсчитать файлы непосредственно в определенном каталоге:

ls dir1 | wc -l

jrajav
источник
Я не хочу делать это для каждой из тысяч каталогов, которые у меня есть ...
jldupont
Тогда используйте Xargs. ls -d */ | xargs -n1 ls | wc -l(Используйте ответ, который вы приняли, если он уже работает, хотя! Это просто, и теперь вы знаете.)
jrajav
Ваше предложение не показало никаких результатов в течение многих секунд, тогда как ответ, который я принял, сделал.
2012 г.
@jrajav этот подход абсолютно не подходит для каталогов с пробелами в них. Вот почему findтак важно. ( не говоря уже -print0и xargs -0уже указал Скотт в другой ответ)
SyntaxError
1
find . -mindepth 1 -type d -print0 | xargs -0 -I{} sh -c 'printf "%4d : %s\n" "$(find {} -type f | wc -l)" "{}"'

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

Тедди катаяма
источник
0

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

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done
derberlinersmurf
источник
0

Вы можете использовать этот код Python. Загрузите интерпретатор, запустив python3и вставив это:

folder_path = '.'
import os, glob
for folder in sorted(glob.glob('{}/*'.format(folder_path))):
    print('{:}: {:>8,}'.format(os.path.split(folder)[-1], len(glob.glob('{}/*'.format(folder)))))

Или рекурсивная версия для вложенных подсчетов:

import os, glob
def nested_count(folder_path, level=0):
    for folder in sorted(glob.glob('{}/'.format(os.path.join(folder_path, '*')))):
        print('{:}{:}: {:,}'.format('    '*level, os.path.split(os.path.split(folder)[-2])[-1], len(glob.glob(os.path.join(folder, '*')))))
        nested_count(folder, level+1)
nested_count('.')

Пример вывода:

>>> figures: 5
>>> misc: 1
>>> notebooks: 5
>>>     archive: 65
>>>     html: 12
>>>     py: 12
>>>     src: 14
>>> reports: 1
>>>     content: 6
>>> src: 1
>>>     html_download: 1
AlexG
источник