Створити розподіл розмірів файлів з командного рядка


16

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

1KB: 4123
2KB: 1920
4KB: 112
...
4MB: 238
8MB: 328
16MB: 29138
Count: 320403345

Я відчуваю, що це не повинно бути занадто поганим, враховуючи цикл і деякий умовний log2 розмір файлів foo, але я не можу зовсім схоже потрапити туди.

Пов'язане запитання: Як я можу знайти файли, що мають більший / менший розмір, ніж x байт? .

Відповіді:


22

Це, здається, працює досить добре:

find . -type f -print0 | xargs -0 ls -l | awk '{size[int(log($5)/log(2))]++}END{for (i in size) printf("%10d %3d\n", 2^i, size[i])}' | sort -n

Його результат виглядає приблизно так:

         0   1
         8   3
        16   2
        32   2
        64   6
       128   9
       256   9
       512   6
      1024   8
      2048   7
      4096  38
      8192  16
     16384  12
     32768   7
     65536   3
    131072   3
    262144   3
    524288   6
   2097152   2
   4194304   1
  33554432   1
 134217728   4
де число зліва - нижня межа діапазону від цього значення до подвоєного значення, а число праворуч - кількість файлів у цьому діапазоні.


Я відредагував вашу відповідь, щоб використати find замість ls, щоб він був рекурсивним і не робив жодного підрахунку каталогів. Хто-небудь хоче взяти тріщину при збиранні лівого стовпчика?
notpeter

Але початкове запитання стосувалося "розподілу розмірів файлів у певній папці", тому міняти lsна "a " неправильно find. Я повертаю його таким, яким він був.
garyjohn

@notpeter: Вибачте, я не визнав вас автором питання. Я змінив свою відповідь, щоб змусити її рекурсивно шукати. У моїй системі, хоча, використовуючи xargsце значно швидше , ніж -exec, тому я використав цей метод.
garyjohn

1
Не хвилюйтесь. Тепер ми можемо просто видалити наші коментарі, робимо вигляд, що це завжди була правильна відповідь. ;)
непетер

14

Виходячи з відповіді garyjohn, ось однолінійний, який також форматує висновок, зрозумілий для людини:

find . -type f -print0 | xargs -0 ls -l | awk '{ n=int(log($5)/log(2)); if (n<10) { n=10; } size[n]++ } END { for (i in size) printf("%d %d\n", 2^i, size[i]) }' | sort -n | awk 'function human(x) { x[1]/=1024; if (x[1]>=1024) { x[2]++; human(x) } } { a[1]=$1; a[2]=0; human(a); printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }'

Ось розгорнута його версія:

find . -type f -print0                                                   \ 
 | xargs -0 ls -l                                                        \
 | awk '{ n=int(log($5)/log(2));                                         \
          if (n<10) n=10;                                                \
          size[n]++ }                                                    \
      END { for (i in size) printf("%d %d\n", 2^i, size[i]) }'           \
 | sort -n                                                               \ 
 | awk 'function human(x) { x[1]/=1024;                                  \
                            if (x[1]>=1024) { x[2]++;                    \
                                              human(x) } }               \
        { a[1]=$1;                                                       \ 
          a[2]=0;                                                        \
          human(a);                                                      \
          printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }' 

У першому awkя визначив мінімальний розмір файлу, щоб зібрати всі файли менше 1 кб в одне місце. По-друге awk, human(x)визначена функція для створення читабельного для людини розміру. Ця частина заснована на одній з відповідей тут: /unix/44040/a-standard-tool-to-convert-a-byte-count-into-human-kib-mib-etc -подобний-дю-лс1

Вихід вибірки виглядає так:

  1k:    335
  2k:     16
 32k:      5
128k:     22
  1M:     54
  2M:     11
  4M:     13
  8M:      3

Я вибрав це рішення для того, щоб дізнатись, які файли мають 128 КК та під тим, щоб встановити розмір запису встановлення ОС на ZFS. Я боюся, що у нього спостерігається уповільнення роботи файлів, менших за розмір запису на 128 Кб, але важко зрозуміти, чому це не враховуючи файли.
AveryFreeman

2

Спробуйте це:

find . -type f -exec ls -lh {} \; | 
 gawk '{match($5,/([0-9.]+)([A-Z]+)/,k); if(!k[2]){print "1K"} \
        else{printf "%.0f%s\n",k[1],k[2]}}' | 
sort | uniq -c | sort -hk 2 

ВИХІД:

 38 1K
 14 2K
  1 30K
  2 62K
  12 2M
  2 3M
  1 31M
  1 46M
  1 56M
  1 75M
  1 143M
  1 191M
  1 246M
  1 7G

ПОЯСНЕННЯ:

  • find . -type f -exec ls -lh {} \;: досить просто: знайдіть файли в поточному режимі та запустіть ls -lhїх

  • match($5,/([0-9.]+)([A-Z]+)/,k);: це дозволить отримати розмір файлу та зберегти кожну відповідність до масиву k.

  • if(!k[2]){print "1K"}: якщо k[2]не визначено розмір файлу <1 К. Оскільки я уявляю, що вам не байдужі такі маленькі розміри, сценарій надрукує 1Kдля всіх файлів розміром <= 1 К.

  • else{printf "%.0f%s\n",k[1],k[2]} : якщо файл більший за 1 К, округніть розмір файлу до найближчого цілого числа та надрукуйте разом із його модифікатором (K, M або G).

  • sort | uniq -c : підраховує кількість надрукованих рядків (розмір файлу).

  • sort -hk 2: сортувати відповідно до другого поля у читаному для людини форматі. Цей спосіб 7Gсортується за 8M.


Я ціную пояснення, думаю, що це корисно для людей, які намагаються це зрозуміти. Однак, ваш сценарій не працює для мене з двох причин. занадто багато відра. З розмірами файлів між 1 К та 1 Г є 2000 відра, половина з яких 1 КБ, половина з яких - 1 МБ. Варто хоч для нового, що для мене 'uniq -c'.
непетер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.