Bir dizindeki dosya sayısını saymanın en iyi yolu nedir?


11

Çıktının ayrıştırılması lstehlikelidir, çünkü bazı korkak karakterleri (boşluklar \n, ...) kırabilir, bir dizindeki dosya sayısını bilmenin en iyi yolu nedir?

Ben genellikle findbu ayrışmayı önlemek için güvenirim , ama benzer şekilde, find mydir | wc -laynı nedenlerle kırılacaktır.

Şu anda Solaris üzerinde çalışıyorum, ancak farklı birliklerde ve farklı kabuklarda taşınabilir olarak bir cevap arıyorum.


3
Bunun bir kopya olduğundan emin değilim, bir şey mi kaçırıyorum?
rahmu

1
Bu bir kopya olabilir, ancak belirtilen sorudan değil. findsize yinelenen sayıda dosya alacaktır ( -maxdepth 1bunu istemiyorsanız kullanın. dosya adındaki find mydir -maxdepth 1 -type f -printf \\n | wc -lözel karakterleri işlememelidir, çünkü asla ilk etapta yazdırılmazlar.)
Anthon

Yanıtlar:


16

Bu numaraya ne dersin?

find . -maxdepth 1 -exec echo \; | wc -l

Gibi taşınabilir olarak findve wc.


5
Bu işe yaramaz ( n+1Debian sistemimdeki dosyaları görüntüler ). Ayrıca normal dosyaları filtrelemez.
Chris Down

4
Az önce jenerik bir örnek verdim. Çalışıyor, ancak nasıl çalıştığı, findkomutu özel ihtiyaçlarınıza nasıl uyarladığınıza bağlıdır . Evet, bu dahil olmak üzere tüm dizinleri içerir .(bu yüzden sonucu olarak görüyorsunuz n+1).
rozcietrzewiacz

Bu hileyi seviyorum, çok zeki; ama bunu yapmanın basit bir yolu olmadığına şaşırdım!
rahmu

3
@ChrisDown OP, normal dosyalar için filtreleme belirtmez, bir dizindeki dosya sayısını ister. N + 1 sorunundan kurtulmak için find . -maxdepth 1 ! -name . -exec echo \; | wc -l; bazı eski sürümleri findyok -not.
Arcege

3
Bunun -maxdepthstandart olmadığını unutmayın (şimdi birkaç başka uygulama tarafından da desteklenen bir GNU uzantısı).
Stéphane Chazelas

11

Bash ile, harici yardımcı programlar olmadan veya döngüler olmadan:

shopt -s dotglob
files=(*)
echo ${#files[@]}

Ksh olarak, yerine shopt -s dotglobgöre FIGNORE=.?(.). Zsh'de, ile değiştirin setopt glob_dotsveya shoptaramayı kaldırın ve kullanın files=(*(D)). (Veya nokta dosyalarını dahil etmek istemiyorsanız satırı bırakın.) Portatif olarak, nokta dosyalarını önemsemiyorsanız:

set -- *
echo $#

Nokta dosyalarını dahil etmek istiyorsanız:

set -- *
if [ -e "$1" ]; then c=$#; else c=0; fi
set .[!.]*
if [ -e "$1" ]; then c=$((c+$#)); fi
set ..?*
if [ -e "$1" ]; then c=$((c+$#)); fi
echo $c

2
Etkinleştirilmediğinde ilk örnek 1boş bir dizin için yazdırılır nullglob. Zsh olarak, a=(*(DN));echo ${#a}birlikte N( nullglob) eleme boş dizin için bir hataya yol açmaz.
nisetama

8
find . ! -name . -prune -print | grep -c /

80'li yılların sonlarına göre oldukça taşınabilir olmalıdır.

Bütün dizin girişleri hariç sayımları O .ve ..geçerli dizinde.

Alt dizinlerdeki dosyaları da saymak için:

find .//. ! -name . | grep -c //

(gerekmediği için Unix V6'ya (1975) bile taşınabilir olmalı -prune)


Sadece olmasa da, bu sayfadaki nadir taşınabilir cevaplardan biri.
xhienne

Bu yanıtı, geçerli dizin ( find dirname ! -name dirname -prune -print) dışındaki dizinler için de işe yaradığını buldum . Kullanmak için herhangi özel bir nedeni var mı diye beri merak edilmiştir grep -c /yerine wc -l(muhtemelen daha yaygın sayımı için kullanılır).
Anthony Geoghegan

1
find dirname ! -name dirnameiçinde başka dizinler varsa çalışmaz dirname. Kullanmak daha iyi find dirname/. ! -name .. wc -lsatır sayısını sayar, yeni satır karakteri bir dosya adında olduğu gibi geçerli olduğundan dosya adları birkaç satırdan yapılabilir.
Stéphane Chazelas

6

Deneyin:

ls -b1A | wc -l

-bOlmayan basılabilir karakterler olacak -Adışındaki tüm dosyaları gösterir .ve ..ve hat (bir boru varsayılan, ama iyi açık olması) başına bir.

Üst düzey komut dosyası dillerini eklediğimiz sürece, Python'da bir satırlık:

python -c 'import os; print len(os.listdir(os.sep))'

Veya tam 'find' ile:

python -c 'import os; print len([j for i in os.walk(os.sep) for j in i[1]+i[2]])'

1

Yoc böyle bir yapıyı kullanabilir:

I=0; for i in * ; do ((I++)); done ; echo $I

Ama korkarım, Argument list too long.dizinde çok fazla dosya olması durumunda hata yapabilirsin . Ancak 10 milyar dosyayla dizinde test ettim ve iyi çalıştı.


3
Kabuk bunları genişletecek şekilde yapılandırılmadığı sürece, bu gizli dosyalar için çalışmaz *.
Lekensteyn

gnu find . -maxdepth 1 -type f | wc -l
Nikhil Mulley

4
@Rush: Bu komut hiçbir zaman "arg listesini çok uzun" olarak yükseltmemelidir. Bu sadece harici komutla olur (asla for.
enzotib

1

Nispeten taşınabilir olması gereken perl'i düşündünüz mü?

Gibi bir şey:

use File::Find;

$counter = 0;

sub wanted { 
  -f && ++$counter
}

find(\&wanted, @directories_to_search);
print "$counter\n";

0

Bunu deneyin => Kullanarak ls & -F (düğüm sayısı için) -i ile seçenekleri ( '/' dizin adının ekler).

ls -ilF | egrep -v '/' | wc -l

0

Bir ile perlbir-liner (okunabilirlik için yeniden biçimlendirilmiş):

perl -e 'opendir($dh, ".");
         while ( readdir($dh) ) {$count++};
         closedir $dh;
         print "$count\n";'

veya

perl -e 'opendir($dh, ".");
         @files = readdir($dh);
         closedir $dh;
         print $#files+1,"\n";'

perlDizileri ikinci sürüm gibi grepveya mapbu sürümle değiştiren işlevleri kullanabilirsiniz . perldoc -f readdirKullanarak bir örnek için bakınız grep.


0

Her zaman kullandığım ve hiç problem yaşamadığım en basit sürüm: ls -b1 | wc -l


Dosya adı bir \nveya başka funky karakter içeriyorsa sorun yaşayabilirsiniz (evet, bazı birleşimler buna izin verir).
rahmu

1
Cevabımı göndermeden önce bunu açıkça denedim ve hiçbir problem yaşamadım. Bunu denemek için \ n içerecek bir dosyayı yeniden adlandırmak için nautilus dosya yöneticisi kullandım.
Peter

Haklısın, böyle çalışmıyor. Bunu ilk test ettiğimde ne yaptığımı bilmiyorum. Tekrar denedim ve cevabımı güncelledim.
Peter

Hayır, komut tamam, ancak zaten benzer bir çözüm var ve gizli dosyalar sayılmıyor.
xhienne

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.