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


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.