Word counter ( wc
) ve piping'i dizinde kaç dosya veya dizin olduğunu saymak için nasıl kullanabilirim /usr/bin
?
Word counter ( wc
) ve piping'i dizinde kaç dosya veya dizin olduğunu saymak için nasıl kullanabilirim /usr/bin
?
Yanıtlar:
Bir yaklaşım, ls
bize 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. -1
Anahtar bizim için yapacağız.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
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 -l
iç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)
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 .
$ 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 grep
dizinleri 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 -l
yukarı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 wc
kullanımı tamamen ve grep
'ın -c
seç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.).
Eğer dosyaları ve dizinleri özyinelemeli olarak bulmanız gerekiyorsa, /usr/bin
muhtemelen taktikleri tamamen değiştirmek ve adlı başka bir aracı kullanmak isteyeceksiniz find
.
$ find /usr/bin | wc -l
4632
(her ne kadar yukarıda /usr/bin
sayılırsa)
Yukarıda kullandığım aynı teknikler , ls
benzer 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 find
gizli dosyalar ( .
ve hariç ..
) içerdiğini unutmayı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 wc
ve ls
bunlarla mücadele etmeyecektir, bu yüzden bunları akılda kullanın.
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 wc
yeni 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 find
kullanmak find
ve bunun yerine bunları saymaktır.
$ 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 wc
satırlar yerine bayt sayma yeteneğini kullanarak noktaları sayıyoruz wc -c
.
/usr/bin
tü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.
ls -l
ya ls -1
da b / c'yi kıracağız çizgileri sayıyoruz, kelimeleri değil! find
Kırabilir, ama yine biz kelimeleri hatları sayma değiliz.
touch $'foo\nbar'
içinde boş bir dizin komutları (diyelim biri tarafından takip ls -1 | wc -l
bir yerine iki dosya bildirir) - kadarıyla olarak bu bir dosya iki satır olduğu için wc
ilgilenir. Yeni ls
satı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).
wc -c
periyotları sayarken bir sorun mu var?
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/bin
sistemimde 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 links
ederseniz, 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?), find
Her 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 find
yoksa, 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/bin
genellikle 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 find
ve GNU ile dosyaları uniq
saymak 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
/ 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
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
.
veya ..
girdileri saymayacağını unutmayın . Dosyayı normal dosyaya göre ayıklamak isteyebilirsiniz.