Komut isteminden dosya boyutlarının dağıtımını oluşturma


16

Birkaç milyon dosyaya sahip bir dosya sistemim var ve belirli bir dizinde dosya boyutlarının yinelemeli olarak dağılımını görmek istiyorum. Bu bazı bash / awk fu ile tamamen yapılabilir gibi hissediyorum, ancak bir el kullanabilirsiniz. Temelde aşağıdaki gibi bir şey istiyorum:

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

Bir döngü ve bazı koşullu log2 dosya boyutu foo göz önüne alındığında bu çok kötü olmamalı gibi hissediyorum, ama oraya oldukça görünemiyorum.

İlgili Soru: x bayttan daha büyük / küçük dosyaları nasıl bulabilirim? .

Yanıtlar:


22

Bu oldukça iyi çalışıyor gibi görünüyor:

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

Çıkışı şöyle görünür:

         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
burada soldaki sayı, bu değerden o değerin iki katına kadar olan bir aralığın alt sınırıdır ve sağdaki sayı bu aralıktaki dosya sayısıdır.


Ben özyinelemeli ve herhangi bir dizin sayma yapmadım böylece ls yerine find kullanmak için cevabınızı düzenledi. Sol sütun çıkışını güzelleştirmek için bir çatlak almak isteyen var mı?
notpeter

Fakat asıl soru bu yüzden değiştirmek için OK değil, "belirli dizindeki dosya boyutları dağılımı" ilgiliydi lsa find. Onu eski haline getiriyorum.
garyjohn

@notpeter: Üzgünüm, sizi sorunun yazarı olarak tanımadım. Cevabımı, tekrar tekrar arama yapmak için değiştirdim. Benim sistemde olsa da, kullanan xargsolduğu ölçüde daha hızlı -execben bu yöntemi kullanılır, böylece.
garyjohn

1
Telaşa gerek yok. Şimdi sadece yorumlarımızı silebiliriz, her zaman doğru cevaptı. ;)
notpeter 14:13

14

Garyjohn'un cevabına dayanarak, çıktıyı insan tarafından okunabilir şekilde formatlayan bir astar:

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) }'

İşte bunun genişletilmiş versiyonu:

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) }' 

Birincisinde awkI tek yere 1kb daha az tüm dosyaları toplamak için minimum dosya boyutu tanımlanır. İkincisinde awk, human(x)insan tarafından okunabilir bir boyut oluşturmak için fonksiyon tanımlanır. Bu bölüm şu cevaplardan birine dayanmaktadır: /unix/44040/a-standard-tool-to-convert-a-byte-count-into-human-kib-mib-etc -like-du-LS1

Örnek çıktı şuna benzer:

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

ZFS'de bir OS kurulumunun kayıt boyutunu ayarlamak için hangi dosyaların 128K ve altında olduğunu bulmak için bu çözümü seçtim. Korkarım 128K kayıt boyutundan daha küçük birçok dosyaya sahip olmanın yavaşlamasını yaşıyor, ancak dosyaları saymadan bu yüzden olup olmadığını bilmek zor.
AveryFreeman

2

Bunu dene:

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 

ÇIKTI :

 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

AÇIKLAMA:

  • find . -type f -exec ls -lh {} \;: yeterince basit, geçerli dizinde dosyaları bulun ve ls -lhüzerinde çalıştırın

  • match($5,/([0-9.]+)([A-Z]+)/,k);: Bu, dosya boyutunu çıkarır ve her eşleşmeyi diziye kaydeder k.

  • if(!k[2]){print "1K"}: k[2]tanımsızsa dosya boyutu <1K'dir. Böyle küçük boyutları umursamadığımı düşündüğüm için, komut dosyası 1Kboyutu <= 1K olan tüm dosyalar için yazdırılacaktır .

  • else{printf "%.0f%s\n",k[1],k[2]} : dosya 1K'dan büyükse, dosya boyutunu en yakın tamsayıya yuvarlayın ve değiştiricisiyle (K, M veya G) birlikte yazdırın.

  • sort | uniq -c : yazdırılan her satırın (dosya boyutu) oluşumlarını sayın.

  • sort -hk 2: okunabilir biçimde ikinci alana göre sıralar. Bu şekilde, 7Gsonra sıralanır 8M.


Açıklamaları takdir ediyorum, anlamaya çalışan insanlar için yararlı olduğunu düşünüyorum. Bununla birlikte, komut dosyanız iki nedenden dolayı benim için çalışmıyor 1) GNU LS'im eski ve bu nedenle 'ls -lh' (K / M / G / T olmayan baytlar ve 2) için farklı insan tarafından okunabilir boyut çıktısı veriyor çünkü çok fazla kova var. 1K ile 1G arasındaki dosya boyutlarında, yarısı 1KB olan ve 1MB olan 2000 kova bulunur. Buna rağmen benim için yeni 'uniq -c' için buna değer.
notpeter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.