Як підрахувати кількість файлів у кожному каталозі?


105

Я в змозі перерахувати всі каталоги від

find ./ -type d

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

find ./ -type d | xargs ls -l | wc -l

Але це підсумовувало загальну кількість повернених рядків

find ./ -type d | xargs ls -l

Чи є спосіб я підрахувати кількість файлів у кожному каталозі?


Ви шукаєте спосіб підрахунку кількості файлів у кожному з підкаталогів безпосередньо під ./?
Tuxdude

5
Як це поза тематичне питання ?? Я хотів би бачити коментарі близьких виборців з розумом! Якщо це поза темою, то куди це належить? супер користувач? Я так не думаю ..
InfantPro'Aravind '

6
shell-скрипт, batch-скрипт знаходяться в межах програмування!
InfantPro'Aravind '

Я вже збирався розмістити пітонічне рішення, тоді я помітив, що питання закрите.
anatoly techtonik

проголосували за його повторне відкриття. Можуть бути й інші відповіді, які можуть бути корисними у багатьох ситуаціях (включаючи програмування скриптів, через що я дійшов до цього питання).
lepe

Відповіді:


110

Якщо припустити, що GNU знайде, дозвольте йому знайти каталоги та дозвольте баш робити все інше:

find . -type d -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

2
Це лише трохи інша версія від наведеної, так: (підказка: її сортування за назвою та його в csv) для x in find . -maxdepth 1 -type d | sort; y = find $x | wc -l; ехо $ х, $ у; зроблено
pcarvalho

5
Чудовий! Поклавши його в єдиний рядок (так це зручно для прямого використання в оболонці):find . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "${#files[@]}" "$dir"; done
lucaferrario

13
Мені потрібно було отримати кількість усіх файлів (рекурсивно рахувати) у кожному підкаталозі. Ця модифікація дає вам таке: find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find $dir -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
OmidS

1
@Kory Зробимо це так:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done | sort -rn -k1
OmidS

1
@OmidS Чудовий oneliner, але $dirв першому коментарі слід містити цитати, щоб правильно обробляти імена режиму з пробілами. :find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
Радек Данилюк

183

Це друкує кількість файлів у каталозі для поточного рівня каталогу:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr

9
На сьогодні найкраще (і найелегантніше) рішення, якщо хочеться рекурсивно перераховувати кількість файлів у каталогах верхнього рівня.
іктоктоп

13
У цьому є дві проблеми: він враховує один файл у каталозі більше, ніж є насправді, і він дає марну рядок, що містить розмір поточного каталогу як "1 розмір ". Обидва можна виправити за допомогою du -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c. Додати | sort -nrдля сортування за кількістю, замість імені каталогу.
десерт

3
Я хотів би зазначити, що це працює і в OSX. (Просто копіювання вставлення поради Linux в оболонку OSX зазвичай не працює.)
Пістос

2
він отримує непотрібний розмір за допомогою du -a. Кращим способом є використання команди find. але головна ідея точно така ж :)
Znik

5
знайти. -типу f | вирізати -d / -f2 | сортувати | uniq -c | sort -nr # виправляє проблеми, згадані десертом
jcomeau_ictx

28
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f щоб знайти всі елементи файлу типу
  • cut -d/ -f2 щоб вирізати їх конкретну папку
  • sort сортувати список імен папок
  • uniq -c щоб повернути кількість підрахунків кожного імені папки

8
Це набагато краще, ніж прийнята відповідь, оскільки ви отримуєте резюме каталогів вищого рівня!
Джейсон Флойд

3
Це має бути прийнятою відповіддю. Просте і зрозуміле.
xssChauhan

1
Найкраща відповідь, яку слід прийняти, - це ця.
loretoparisi

1
Простий, елегантний та ідеальний для моїх потреб.
RichR

Ідеально. І може бути розширено для підрахунку підкаталогів, замінивши специфікатори поля списком специфікаторів поля. Наприклад,:find . -type f | cut -d/ -f2,3 | sort | uniq -c
algal

15

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

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

Єдине завдання в цьому випадку, якщо у вас є імена файлів або імена каталогів, що містять символ нового рядка, що малоймовірно. Якщо вам справді доводиться турбуватися про нові рядки в іменах файлів або іменах каталогів, я пропоную вам їх знайти та виправити, щоб вони не містили нових рядків (і тихо переконуйте винну сторону у помилці їх шляху).


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

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

Перший візерунок фіксує початок імені, крапки, косою рисою, ім'я до наступної косої риски та косою рисою, і замінює рядок лише на першу частину, так:

./dir1/dir2/file1

замінюється на

./dir1/

Друга заміна захоплює файли безпосередньо в поточному каталозі; вони не мають косою рисою в кінці, а їх замінюють на ./. Сортування та підрахунок тоді працює лише на кількість імен.


1
Це не виводить імена каталогів, які не містять жодних файлів. Не впевнений, чи потрібно це.
Остін Філіпс

Щоправда, це не так. 'Це не особливо тривіально, щоб це виправити, оскільки порожні імена каталогів не гарантуються навіть у вихідних файлах find. Деякі можуть: якщо є файл dir1/dir2/dir3/file1, але він dir1/dir2містить лише підкаталоги (немає простих файлів), ви можете зробити висновок про його наявність. Але якщо dir1/dir4файлів немає, його ім'я просто не відображається.
Джонатан Леффлер

Дуже корисна відповідь, якщо ви просто хочете побачити підкаталоги поточного каталогу.
xixixao

Просто зупинився, щоб сказати спасибі. Через 3 роки після того, як це було опубліковано, я шукав підрахунок папок другого рівня в папці. Ваша публікація врятувала мене, можливо, багато годин поворушившись сідом, знайдіть і хто знає що ще
Корвін

13

Ось один із способів зробити це, але, мабуть, не найефективніше.

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

Видає такий вихід, з ім'ям каталогу, за яким слідує кількість записів у цьому каталозі. Зауважте, що кількість вихідних даних також буде включати записи каталогів, які можуть бути не такими, які ви хочете.

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0

Це здається дуже дорогим для запуску 3 команди ( bash, ls, wc) для кожного каталогу , знайденого find.
Джонатан Леффлер

@JonathanLeffler погодився, звідси і перший рядок моєї відповіді. Ваше рішення краще.
Остін Філіпс

класно, це те, що я шукаю, чи можу я запитати, що таке "-" наприкінці?
одного разу

1
@once The - належить команді bash, яку буде породжено xargs. З man bash, A -- signals the end of options and disables further option processing. У цьому випадку це не дозволить файлу з назви, який було знайдено як частину знахідки, не стати частиною аргументу обробки для bash.
Остін Філіпс

8

У всіх інших рішень є той чи інший недолік.

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'

Пояснення:

  • -type d: нас цікавлять каталоги.
  • -readable: Ми хочемо їх лише, якщо можливо перелічити файли в них. Зауважте, що findвсе-таки виникла помилка, коли вона намагатиметься шукати в них більше каталогів, але це заважає викликати -execїх.
  • -exec sh -c BLAH sh {} ';': для кожного каталогу запустіть цей фрагмент сценарію, $0встановивши shі $1встановіть на ім’я файлу.
  • printf "%s " "$1": портативно та мінімально друкуйте ім’я каталогу, після чого слід лише пробіл, а не новий рядок.
  • ls -1UA: список файлів, по одному на рядок, у порядку каталогу (щоб уникнути затримки труби), виключаючи лише спеціальні каталоги .та..
  • wc -l: порахуйте рядки

1
Модифікація для відображення файлів, що рахуються спочатку на рядку, та їх сортування:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh {} ';' | sort -n
Євгеній Сергєєв

він виконує оболонку багато разів, тоді він повільний і високо використовує ресурси.
Znik

6

Трохи модифікована версія відповіді Себастьяна, використовуючи findзамість du(щоб виключити накладні розміри файлів, які duпотрібно виконати, і які ніколи не використовуються):

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

-mindepth 2Параметр використовується для виключення файлів у поточному каталозі. Якщо ви видалите його, ви побачите купу рядків, таких як:

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(так само, як і duваріант на основі)

Якщо вам також потрібно порахувати файли в поточному каталозі, використовуйте цю розширену версію:

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr

Вихід буде таким:

  234 dir1
  123 dir2
   42 .

5

Це також можна зробити за допомогою перекидання ls замість знаходження

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

Пояснення:

for f in */; - циклічно про всі каталоги

do echo "$f -> - роздрукувати кожне ім'я каталогу

$(ls $f | wc -l) - викликати ls для цього каталогу та рахувати рядки


1
Це не працює належним чином, якщо імена каталогів містять пробіли.
Ксилол

Спробуйтеfor f ./* ; do echo $f $(ls "$f" | wc -l); done
4ndt3s

3

Це повинно повернути ім'я каталогу, а потім кількість файлів у каталозі.

findfiles() {
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)
}

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;

Приклад виводу:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

export -fПотрібно , оскільки -execаргумент findне дозволяє не виконує функцію Баша , якщо ви викликаєте Баш явно, і вам потрібно експортувати функцію , певну в поточній області в нову оболонку в явному вигляді.


Це здається надмірно складним. Мені також здається, що він дає сукупні підрахунки для ієрархії каталогів, таких як ./dir1/dir2/dir3(підрахунок файлів у dir1всіх підкаталогах разом, а не підрахунок файлів dir1/dir2/dir3окремо від тих, що входять, dir1/dir2і обидва окремо від тих, що входять /dir1).
Джонатан Леффлер

Я зрозумів, що цього хоче автор. Якщо це не так, то я згоден, що відповідь не стосується питання.
Tuxdude

1
@JonathanLeffler - Добре, прочитавши ще раз питання, я зрозумів, що ти маєш рацію - відповідно змінив відповідь.
Tuxdude

2

Я поєднав відповідь @glenn jackman та відповідь @ pcarvalho (у списку коментарів щось не так з відповіддю pcarvalho, оскільки функція контролю стилю над символом ' ' '(backtick)).

Мій сценарій може сприймати шлях як доповнення та сортувати список каталогів як ls -l, також він може вирішувати проблему "пробілу у імені файлу" .

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "${#files[@]}" "$dir"
done
FS="$OLD_IFS"

Моя перша відповідь у stackoverflow, і я сподіваюся, що це може комусь допомогти ^ _ ^


1

знайти. -тип f -printf '% h \ n' | сортувати | uniq -c

приклад:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot

0

Я спробував з деякими іншими тут, але в кінцевому підсумку вкладені підпапки, що входять до числа файлів, коли я хотів лише файли. Це друкує ./folder/path<tab>nnnкількість файлів, не включаючи папки, для кожної підпапки в поточній папці.

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done

0

Простий спосіб рекурсивного пошуку файлів заданого типу. У цьому випадку .jpg файли для всіх папок у поточному каталозі:

find . -name *.jpg -print | wc -l


0

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

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

Кредити: https://unix.stackexchange.com/a/386135/354980


0

Це може бути ще одним способом перегляду структур каталогів та надання глибинних результатів.

find . -type d  | awk '{print "echo -n \""$0"  \";ls -l "$0" | grep -v total | wc -l" }' | sh 

0

Я редагував сценарій, щоб виключити всі node_modulesкаталоги всередині аналізованого.

Це можна використати для перевірки, чи кількість файлів проекту перевищує максимальну кількість, з якою може обробляти дисер.

find . -type d ! -path "*node_modules*" -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

Щоб перевірити максимальну кількість файлів, які може переглядати ваша система:

cat /proc/sys/fs/inotify/max_user_watches

node_modules папка повинна бути додана до ваших IDE / редакторів, що виключаються у повільних системах, а кількість інших файлів в ідеалі не повинна перевищувати максимальну (що можна змінити).


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