Belirli bir dizinde kaç dosya ve dizin olduğunu bulmak için wc ve piping nasıl kullanılır?


10

Word counter ( wc) ve piping'i dizinde kaç dosya veya dizin olduğunu saymak için nasıl kullanabilirim /usr/bin?


Bu ödev ?? Yardım istemek sorun değil, sadece bu şekilde tanımlayın.
slm

evet öyle ama Linux'ta yeni olduğum ve çok karmaşık olabileceğinden bir şeyi nasıl başaracağım hakkında bir fikir edinmek için buraya gönderiyorum. Ve yukarıdaki soruyu bu komutla zaten çözdüm
nakit

ls / bin / usr / bin | sırala | uniq | wc -
nakit

np. Yardım istemek gayet iyi! Sadece insanların bilmesi için etiketleyin, buradaki herkes genellikle Unix'in daha ince noktalarını öğrenmeye çalışan insanlara yardım etmekten mutluluk duyar.
slm

Yanıtlar:


13

Bir yaklaşım, lsbize dosyaların bir listesini vermek için faydalanmak olacaktır , ancak bu listenin her satırda yalnızca 1 dosya veya dizin göstermesini garanti ediyoruz. -1Anahtar bizim için yapacağız.

$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC

Misal

Yukarıdaki örnek verileri boş bir dizinde oluşturun.

$ mkdir dir{1..3}
$ touch file{A..C}

Kontrol et:

$ ls
dir1  dir2  dir3  fileA  fileB  fileC

Şimdi saymak wc -liçin ls -1çıktıdaki bir dosyaya veya dizine karşılık gelen satır sayısını saymak için kullanabilirsiniz .

$ ls -1 | wc -l
6

(ancak gizli dosyaları içermediğini unutmayın)

Dosyaları veya dizinleri sayma, sadece birlikte değil

Dosya veya dizinleri saymak için taktiğinizi biraz değiştirmeniz gerekir. Bu durumda ls -l, dizin ve aa dosyasının ne olduğunu gösterdiğinden kullanırım .

Misal

$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileC

Sonra grepdizinleri veya olmayan dizinleri filtrelemek için kullanabiliriz :

# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3

# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileC

Şimdi wc -lyukarıdakileri saymak için tekrar kullanın:

# directories
$ ls -l | grep "^d" | wc -l
3

# regular files
$ ls -l | grep "^-" | wc -l
3

Rağmen, önleyebilirsiniz wckullanımı tamamen ve grep'ın -cseçeneği:

$ ls -l | grep -c '^d'

(yine gizli dosyalar dahil edilmez. Dizinlerin ve normalin iki tür dosya olduğunu unutmayın. Adlandırılmış yöneltmeler, sembolik bağlantılar, cihazlar, soketler ... gibi daha birçok dosya vardır.).

özyineleme

Eğer dosyaları ve dizinleri özyinelemeli olarak bulmanız gerekiyorsa, /usr/binmuhtemelen taktikleri tamamen değiştirmek ve adlı başka bir aracı kullanmak isteyeceksiniz find.

Misal

$ find /usr/bin | wc -l
4632

(her ne kadar yukarıda /usr/binsayılırsa)

Yukarıda kullandığım aynı teknikler , lsbenzer bir şey yapmak için kullanılabilir ls, ancak genellikle çıktıyı ayrıştırmak için iyi bir araç değildir. findÖte yandan, bunun için inşa edilmiş ve dosyaları veya dizinleri bulmak için anahtarlar sunuyor.

# find files
$ find /usr/bin -type f

# find directories
$ find /usr/bin -type d

(bu sefer findgizli dosyalar ( .ve hariç ..) içerdiğini unutmayın ).

yeni satırların?

Yeni satır karakterinin neden dosya adları veya dizin adları oluştururken yasal bir karakter olduğunu anlayamadım. Bu yüzden yukarıda tartışılan yöntemler kullanılarak wcve lsbunlarla mücadele etmeyecektir, bu yüzden bunları akılda kullanın.

Misal

Yeni satırlarla bir dizin ve dosya adı oluşturun.

$ mkdir $'dir4\n5'
$ touch $'fileD\nE'

ls onları doğru gösterir:

$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E

Ancak wcyeni satır içeren dizin ve dosyaları bir değil 2 öğe olarak sayar.

$ ls -1 | wc -l
10

Bu sorunun üstesinden gelmek için bir yöntem, eğer GNU uygulamasını kullanıyorsa, bulduğu her dosya yerine başka bir şey basma yeteneğini findkullanmak findve bunun yerine bunları saymaktır.

Misal

$ find . -printf . | wc -c
9

Burada, geçerli dizindeki (hariç ..) her şeyi buluyoruz ve her biri için bir nokta ( .) yazdırıyoruz ve daha sonra wcsatırlar yerine bayt sayma yeteneğini kullanarak noktaları sayıyoruz wc -c.

Referanslar


İçindeki dosyaların /usr/bintümü iyi biçimlendirilecek olsa da (boşluk içermeyecek olsa da, teknik olarak bile sadece echo * | wc -w), bunların hepsinin yeni satırlar içeren dosya adlarını bozacağına dikkat etmek önemlidir.
2013

@evilsoup - hayır inanmıyorum ls -lya ls -1da b / c'yi kıracağız çizgileri sayıyoruz, kelimeleri değil! findKırabilir, ama yine biz kelimeleri hatları sayma değiliz.
slm

Demek istediğim, dosyalar yeni satırlar içeriyorsa (sanırım, şu anda Windows'tayım, bu yüzden test edemiyorum) kırılacak . Yani touch $'foo\nbar'içinde boş bir dizin komutları (diyelim biri tarafından takip ls -1 | wc -lbir yerine iki dosya bildirir) - kadarıyla olarak bu bir dosya iki satır olduğu için wcilgilenir. Yeni lssatırları başka bir karakterle değiştirmedikçe (öyle olduğunu sanmıyorum, ama yine de şu anda test edecek bir konumda değilim).
2013

@evilsoup - doğru, yeni satır karakter. yasal bir karakterdir. ve bu tür dosya adlarıyla doğru bir şekilde mücadele edemezdi.
slm

@StephaneChazelas - wc -cperiyotları sayarken bir sorun mu var?
slm

5

GNU ile find, her bir dosya türünün sayısını bir dizin altında yinelenen bir şekilde almak istiyorsanız , şunları yapabilirsiniz:

find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/l/symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

On /usr/binsistemimde ki verir:

   3727 regular files
    710 symbolic links

Açık /dev:

     83 block devices
    203 character devices
     31 directories
    426 symbolic links
      1 FIFOs
      1 Unix domain sockets

Sembolik bağlar için, onları işaret ettikleri dosyanın türü olarak saymayı tercih symbolic linksederseniz, bunu şu şekilde değiştirebilirsiniz:

find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/N/broken symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

Şimdi benim için verir /usr/bin:

      1 directories
   4434 regular files
      2 broken symbolic links

(bozuk bir sembolik bağlantı find, dosyanın bulunmadığı veya erişiminizin olmadığı bir dizinde olduğu veya dosya yolunun çözünürlüğünde bir döngü olduğu için türünü belirleyemeyen bir dosyaya bağlantı noktasıdır. Benim durumumda, şimdi gitmiş olan dosyalara sembolik olan 2).

Bunların hiçbiri sayılmaz .ve ... Bunların dahil edilmesini istiyorsanız (neden yaptın?), findHer dizin için orada olduklarını varsaymak ve sistematik olarak saymaktan başka bir yol yoktur :

find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
  -type d -printf 'd\nd\n' \)  | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/l/symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

Sonra benim verir /usr/bin:

      2 directories
   3727 regular files
    710 symbolic links

GNU'ya erişiminiz findyoksa, ilkini şu şekilde yeniden yazabilirsiniz:

find /some/dir/. ! -name . \( \
  -type f -exec printf '%.0sregular files\n' {} + -o \
  -type d -exec printf '%.0sdirectories\n' {} + -o \
  -type l -exec printf '%.0ssymbolic links\n' {} + -o \
  -type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
  -type b -exec printf '%.0sblock devices\n' {} + -o \
  -type c -exec printf '%.0scharacter devices\n' {} + -o \
  -type p -exec printf '%.0sFIFOs\n' {} + -o \
  -exec printf '%.0sothers\n' {} + \) | sort | uniq -c

Şimdi, kesinlikle, dosyaları değil dizin girişlerini sayıyoruz . Benzeri bir dizin /usr/bingenellikle aynı dosyaya işaret eden birkaç giriş içerir. Örneğin, burada, ben var:

$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview

Bunlar aynı dosyaya 3 dizin girişi (diğer adıyla sabit bağlantılar) (672252 kodlu inode ile). Dizin girişleri yerine ve GNU findve GNU ile dosyaları uniqsaymak için (görmezden gelinme .ve ..diğer dizinlere sabit bağlantılar olan dosyalar):

find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
  sort -u |
  cut -f1 |
  uniq -c |
  sed '
    s/f/regular files/;t
    s/d/directories/;t
    s/l/symbolic links/;t
    s/s/Unix domain sockets/;t
    s/b/block devices/;t
    s/c/character devices/;t
    s/p/FIFOs/;t
    s/d/Doors/;t
    s/n/network special files/;t
    s/.$/others (&)/'

Benim /usr/binüzerimde:

   3711 regular files
    710 symbolic links

0

/ Usr / bin altındaki tüm dosyaları yinelemeli olarak mı yoksa ilk düzeyin hemen altında mı istediğinizi söylemediniz. Ayrıca, saydığınız kelimeleri nasıl elde edeceksiniz? Öğrenmenin olağan yolu, wc içine find çalıştırmaktır. Şunun gibi: find / usr / bin | wc -l Find orada her şeyi, dizinleri ve dosyaları listeler. Wc -l bulma çıktısındaki tüm satırları sayar. Bu bir sınıf ödevi mi? Eğer öyleyse sorun değil ama cevabı daha dikkatli bir şekilde uyarlayabilmem için neden bu bilgiye ihtiyaç duyduğunuzu merak ediyordum. Daha fazlasına ihtiyacınız varsa lütfen bana bildirin. Costa


0

Bash'da, harici araçlar olmadan.

cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"

Bash'da, harici araçlar ve özyineleme olmadan.

shopt -s globstar; shopt -s dotglob 
for dir in **/*/; do 
  unset d f
  for files in "$dir"*; do 
    [[ -f $files ]] && ((++f))
    [[ -d $files ]] && ((++d))
  done; 
  printf '%s\n' "$dir -  files: ${f:-0} - directories: ${d:-0}"
done

İkincisinin, yinelenirken sembol bağlantılarını takip edeceğini (ve normal dosyalara olan sembolik bağlantıları normal dosya olarak ve dirseklere dirs olarak dirs olarak sayar) geçerli dizindeki dosyaları ve dizinleri saymayacağını ve sayıları .veya ..girdileri saymayacağını unutmayın . Dosyayı normal dosyaya göre ayıklamak isteyebilirsiniz.
Stéphane Chazelas
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.