Her dizindeki dosya sayısı nasıl hesaplanır?


106

Tüm dizinleri şu şekilde listeleyebiliyorum:

find ./ -type d

Aşağıdaki komutu kullanarak her dizinin içeriğini listelemeye ve her dizindeki dosya sayısını saymaya çalıştım

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

Ancak bu, tarafından döndürülen toplam satır sayısını özetledi.

find ./ -type d | xargs ls -l

Her dizindeki dosya sayısını sayabilmemin bir yolu var mı?


Doğrudan altındaki alt dizinlerdeki dosyaların sayısını saymanın bir yolunu ./mu arıyorsunuz?
Tuxdude

5
Bu nasıl konu dışı bir soru? Yakın seçmen yorumlarını mantıklı görmek istiyorum! Bu konu dışı ise, bu nereye ait? süper kullanıcı? Sanmıyorum ..
InfantPro'Aravind '

6
kabuk-betik, toplu-betik programlama kapsamı altındadır!
InfantPro'Aravind '

Pythonic çözümünü göndermek üzereydim, sonra sorunun kapandığını fark ettim.
anatoly techtonik

yeniden açmak için oy kullandı. Pek çok durumda yararlı olabilecek başka yanıtlar olabilir (bu soruya ulaşmamın nedeni olan komut dosyası programlama dahil).
lepe

Yanıtlar:


113

GNU'nuzun bulduğunu varsayarak, dizinleri bulmasına izin verin ve gerisini bash'ın yapmasına izin verin:

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

2
Yukarıdakinden biraz farklı bir versiyonu, bu yüzden: (ipucu: isme göre sıralanmış ve csv olarak) x in find . -maxdepth 1 -type d | sort; do y = find $x | wc -l; echo $ x, $ y; bitti
pcarvalho

5
Muhteşem bir tane! Tek bir satıra koymak (yani kabukta doğrudan kullanım için rahattır):find . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "${#files[@]}" "$dir"; done
lucaferrario

14
Her alt dizindeki tüm dosyaların sayısını (yinelemeli olarak sayılır) almam gerekiyordu. Bu değişiklik size şunları sağlar: 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 Aşağıdakiler yapacak: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 Harika oneliner, ancak beyaz boşluklu $dirdir isimlerini doğru şekilde işlemek için ilk yorumunuzda tırnak içinde olmalıdır. :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
Radek Daniluk

184

Bu, geçerli dizin seviyesi için dizin başına dosya sayısını yazdırır:

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

9
En üst düzey dizinlerdeki dosya sayısını yinelemeli olarak listelemek isterse, açık farkla en iyi (ve en zarif) çözüm.
itoctopus

13
Bunun iki sorunu vardır: Gerçekte olduğundan daha fazla dizin başına bir dosya sayar ve geçerli dizinin boyutunu " 1 boyut " olarak içeren işe yaramaz bir satır verir . Her ikisi de ile düzeltilebilir du -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c. | sort -nrDizin adı yerine sayıya göre sıralamak için ekleyin .
tatlı

3
Bunun OSX'te de çalıştığını belirtmek isterim. (Linux tavsiyelerini bir OSX kabuğuna kopyalayıp yapıştırmak genellikle işe yaramaz.)
Pistos

2
du -a ile gereksiz boyuta getirir. Daha iyi yol, bul komutunu kullanmaktır. ama ana fikir tamamen aynı :)
Znik

5
bul. tipi f | kesim -d / -f2 | sırala | uniq -c | sort -nr # tatlı tarafından bahsedilen sorunları düzeltir
jcomeau_ictx

29
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f tip dosyasının tüm öğelerini bulmak için
  • cut -d/ -f2 belirli klasörlerini kesmek için
  • sort klasör adları listesini sıralamak için
  • uniq -c her klasör adının kaç kez sayıldığını döndürmek için

8
Bu, en üst düzey dizinlerin bir özetini aldığınız için kabul edilen yanıttan çok daha iyidir!
Jason Floyd

3
Kabul edilen cevap bu olmalıdır. Basit ve anlaşılır.
xssChauhan

1
Kabul edilmesi gereken en iyi cevap budur.
loretoparisi

1
Sade, zarif ve ihtiyaçlarım için mükemmel.
RichR

Mükemmel. Alan belirleyicilerinin bir alan belirleyiciler listesiyle değiştirilmesiyle alt dizinleri saymak için genişletilebilir. Ör ,:find . -type f | cut -d/ -f2,3 | sort | uniq -c
algal

16

Tüm dosyaları bulmayı, dosya adlarını kaldırmayı, her dosya için yalnızca dizin adını içeren bir satır bırakmayı ve ardından her dizinin görünme sayısını saymayı düzenleyebilirsiniz:

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

Buradaki tek sorun, herhangi bir dosya adınız veya bir satırsonu karakteri içeren dizin adlarına sahip olmanızdır ki bu pek olası değildir. Dosya adlarında veya dizin adlarında yeni satırlar hakkında gerçekten endişelenmeniz gerekiyorsa, onları bulmanızı ve yeni satırlar içermemeleri için düzeltmenizi öneririm (ve suçlu tarafı kendi yollarının hatasına sessizce ikna edin).


Geçerli dizinin her bir alt dizinindeki dosyaların sayısıyla ilgileniyorsanız, herhangi bir alt dizindeki dosyaları ve hemen alt dizindeki dosyalarla birlikte saymak istiyorsanız, sedkomutu yalnızca yazdıracak şekilde uyarlarım üst düzey dizin:

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

İlk kalıp, adın başlangıcını, noktayı, eğik çizgiyi, bir sonraki bölü çizgisine kadar olan adı ve eğik çizgiyi yakalar ve çizgiyi yalnızca ilk bölümle değiştirir, bu nedenle:

./dir1/dir2/file1

ile değiştirilir

./dir1/

İkinci değiştirme, dosyaları doğrudan geçerli dizinde yakalar; sonunda bir eğik çizgi yoktur ve bunların yerini alır ./. Sıralama ve sayma, yalnızca adların sayısına göre çalışır.


1
Bu, herhangi bir dosya içermeyen dizin adlarını vermez. Bunun gerekli olup olmadığından emin değilim.
Austin Phillips

Doğru değil. Boş dizin adlarının çıktısında görünmesi bile garanti edilmediğinden, bunu düzeltmek özellikle önemsiz değildir find. Bazıları olabilir: bir dosya varsa dir1/dir2/dir3/file1, ancak dir1/dir2yalnızca alt dizinler içeriyorsa (düz dosyalar yoksa), varlığını anlayabilirsiniz. Ancak dir1/dir4dosya yoksa , adı görünmez.
Jonathan Leffler

Sadece mevcut dizinin alt dizinlerini görmek istiyorsanız çok faydalı bir cevap.
xixixao

Teşekkür etmek için uğradım. Bunun gönderilmesinden 3 yıl sonra, klasör başına 2. düzey klasörleri saymak istiyordum. Gönderiniz sed, bul ve kim bilir başka ne olduğunu potansiyel olarak saatlerce kurcalamaktan kurtardı
Corvin

13

İşte bunu yapmanın bir yolu, ancak muhtemelen en verimli olanı değil.

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

Dizin adı ve ardından bu dizindeki girişlerin sayısıyla bu şekilde çıktı verir. Çıktı sayısının, istediğinizi olmayabilecek dizin girdilerini de içereceğini unutmayın.

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

Bu 3 komutları (çalıştırmak için çok pahalı görünüyor bash, ls, wcbulduğu her dizin için) find.
Jonathan Leffler

@JonathanLeffler Kabul edildi, cevabımın ilk satırı bundan dolayı. Çözümünüz daha iyi.
Austin Phillips

harika, aradığım şey bu, sonunda '-' ne olduğunu sorabilir miyim?
kez

1
@once - xargs tarafından oluşturulacak olan bash komutuna aittir. Gönderen man bash, A -- signals the end of options and disables further option processing. Bu durumda, bulgunun bir parçası olarak bulunan yanlış adlandırılmış bir dosyanın bash için argüman işlemenin bir parçası haline gelmesini önleyecektir.
Austin Phillips

8

Diğer herkesin çözümünün bir dezavantajı vardır.

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

Açıklama:

  • -type d: dizinlerle ilgileniyoruz.
  • -readable: Yalnızca içindeki dosyaları listelemek mümkünse istiyoruz . findİçlerinde daha fazla dizin aramaya çalıştığında yine de bir hata vereceğini unutmayın , ancak bu -execonları aramayı engeller .
  • -exec sh -c BLAH sh {} ';': Her dizin için, ile, bu komut parçasını çalıştırmak $0için sette shve $1dosya adına seti.
  • printf "%s " "$1": dizin adını taşınabilir ve minimum düzeyde yazdırın, ardından satırsonu değil, yalnızca bir boşluk ekleyin.
  • ls -1UA: sadece özel dizinler hariç olmak üzere, dosyaları her satırda bir tane olacak şekilde dizin sırasına göre (borunun durmasını önlemek için) listeleyin .ve..
  • wc -l: satırları say

1
Satırda ilk olarak dosya sayısını göstermek ve onlara göre sıralamak için değişiklik:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh {} ';' | sort -n
Evgeni Sergeev

kabuğu birçok kez çalıştırır, sonra yavaştır ve kaynakları çok kullanır.
Znik

6

Sebastian'ın yanıtının findyerine du( dugerçekleştirilmesi gereken ve asla kullanılmayan dosya boyutuyla ilgili ek yükü hariç tutmak için) yerine kullanılan biraz değiştirilmiş versiyonu :

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

-mindepth 2parametresi, geçerli dizindeki dosyaları dışlamak için kullanılır. Kaldırırsanız aşağıdaki gibi bir dizi satır görürsünüz:

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

( dutabanlı varyantın yaptığı gibi)

Geçerli dizindeki dosyaları da saymanız gerekiyorsa, bu gelişmiş sürümü kullanın:

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

Çıktı aşağıdaki gibi olacaktır:

  234 dir1
  123 dir2
   42 .

5

Bu ayrıca find yerine ls üzerinden döngü yaparak da yapılabilir.

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

Açıklama:

for f in */; - tüm dizinlerde döngü

do echo "$f -> - her dizin adını yazdırın

$(ls $f | wc -l) - bu dizin için ls'yi arayın ve satırları sayın


1
Dizin adları boşluklar içeriyorsa bu düzgün çalışmaz.
Xylol

Deneyinfor f ./* ; do echo $f $(ls "$f" | wc -l); done
4ndt3s

3

Bu, dizin adını ve ardından dizindeki dosya sayısını döndürmelidir.

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

export -f findfiles

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

Örnek çıktı:

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

Bu export -fgereklidir, çünkü -execargümanı, findaçıkça bash'ı çağırmadığınız sürece bir bash işlevinin çalıştırılmasına izin vermez ve geçerli kapsamda tanımlanan işlevi yeni kabuğa açıkça aktarmanız gerekir.


Bu aşırı derecede karmaşık görünüyor. Bana aynı zamanda bir dizin hiyerarşisi için kümülatif sayımlar veriyor gibi görünüyor ./dir1/dir2/dir3(dosyaları içindekilerden ve her ikisini de içeridekilerden ayrı olarak dir1saymak yerine, içindeki dosyaları ve alt dizinlerini bir arada saymak ). dir1/dir2/dir3dir1/dir2/dir1
Jonathan Leffler

Yazarın istediği şeyin bu olduğunu anladım. Durum bu değilse, cevabın soruyla ilgili olmadığını kabul ediyorum.
Tuxdude

1
@JonathanLeffler - Tamam, soruyu bir kez daha okudum, haklı olduğunu anladım - cevabı buna göre değiştirdim.
Tuxdude

2

Ben kombine @glenn Jackman cevabı ve pcarvalho cevabı @ (yorum listesinde, pcarvalho yanıt ile bir terslik mi var çünkü 'karakterinin ekstra stil kontrol işlevi ` ' (ters tırnak)).

Komut dosyam yolu bir artırma olarak kabul edebilir ve dizin listesini şu şekilde sıralayabilir ls -l, ayrıca "dosya adında boşluk" sorununu da çözebilir .

#!/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'daki ilk cevabım ve umarım birine yardımcı olabilir ^ _ ^


1

bul. -tipi f -printf '% h \ n' | sırala | uniq -c

örneğin verir:

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

0

Buradaki diğerlerinden bazılarını denedim, ancak yalnızca dosyaları istediğimde dosya sayısına dahil edilen alt klasörlerle sonuçlandım. Bu ./folder/path<tab>nnn, geçerli klasördeki her bir alt klasör için alt klasörler hariç dosya sayısı ile yazdırılır .

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

0

Belirli bir türdeki dosyaları yinelemeli olarak bulmanın kolay yolu. Bu durumda, geçerli dizindeki tüm klasörler için .jpg dosyaları:

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


0

Bir dizindeki görüntülerin sayısını saymak ve çıktıyı görüntü uzantısına göre düzenlemek için dosyaları yinelemeli olarak geçen süper hızlı bir mucize komutu:

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

Krediler: https://unix.stackexchange.com/a/386135/354980


0

Bu, dizin yapılarına göz atmanın ve derinlik sonuçları sağlamanın başka bir yolu olabilir.

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

0

node_modulesAnaliz edilen dizin içindeki tüm dizinleri hariç tutmak için komut dosyasını düzenledim .

Bu, proje dosya sayısının dosya izleyicisinin işleyebileceği maksimum sayıyı aşıp aşmadığını kontrol etmek için kullanılabilir.

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

Sisteminizin izleyebileceği maksimum dosya sayısını kontrol etmek için:

cat /proc/sys/fs/inotify/max_user_watches

node_modules klasör, yavaş sistemlerde IDE / editör hariç tutulan yollarınıza eklenmelidir ve diğer dosya sayısı ideal olarak maksimum değeri aşmamalıdır (yine de değiştirilebilir).


-1

Bu genel sayımı verecektir.

for file in */; do echo "$file -> $(ls $file | wc -l)"; done | cut -d ' ' -f 3| py --ji -l 'numpy.sum(l)'

Hayır olmayacak. Yalnızca bir düzey alt dizini dikkate alır.
Kusalananda
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.