Кількість файлів у кожному підкаталозі


22

Я хотів би, щоб команда BASH перерахувала лише кількість файлів у кожному підкаталозі каталогу.

Наприклад , в каталозі /tmpтам dir1, dir2... Я хотів би бачити:

`dir1` : x files 
`dir2` : x files ...

Відповіді:


33

Якщо припустити, що потрібно лише рекурсивний підрахунок файлів, а не каталогів та інших типів, щось подібне повинно працювати:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done

Крім того, я отримую "find: попередження: ви вказали параметр -maxdepth після аргументу не-параметр -type, але параметри не є позиційними (-maxdepth впливає на тести, визначені перед ним, а також на ті, що вказані після нього). Будь ласка, вкажіть параметри перед іншими аргументами ».
jldupont

2
Обидві відповіді, наведені до цих пір, дадуть неправильні результати, мабуть, якщо є файли, імена яких містять символи нового рядка. Ви можете впоратися з цим find-print0 | xargs -0....
Скотт,

@jldupont: перемістіть аргументи глибини перед "типом d", я відредагував відповідь.
Тор

Так, і дозвольте додати інформацію про те, що це відмінне рішення не прийме жодних зовнішніх змінних і таким чином буде працювати з bash alias!!
синтаксичний помилок

швидко, і трубопроводи 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

Використання знахідки - це безумовно шлях, якщо ви хочете рахувати рекурсивно, але якщо ви просто хочете підрахунок файлів безпосередньо під певним каталогом:

ls dir1 | wc -l


Я не хочу робити цього для кожного з 1000-х каталогів, які я там маю ...
jldupont

Потім використовуйте xargs. ls -d */ | xargs -n1 ls | wc -l(Однак скористайтеся прийнятою вами відповіддю, якщо вона вже працює! Це просто А тепер ви знаєте.)
jrajav

Ваша пропозиція не показала результатів протягом багатьох секунд, тоді як відповідь, яку я прийняв, це зробив.
jldupont

@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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.