Wie kann ich mit word counter ( wc
) und Piping zählen, wie viele Dateien oder Verzeichnisse sich im /usr/bin
Verzeichnis befinden?
Wie kann ich mit word counter ( wc
) und Piping zählen, wie viele Dateien oder Verzeichnisse sich im /usr/bin
Verzeichnis befinden?
Antworten:
Ein Ansatz wäre ls
, uns eine Liste der Dateien zu geben, aber wir möchten, dass diese Liste garantiert nur 1 Datei oder Verzeichnis pro Zeile anzeigt. Der -1
Schalter erledigt dies für uns.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Erstellen Sie die obigen Beispieldaten in einem leeren Verzeichnis.
$ mkdir dir{1..3}
$ touch file{A..C}
Prüfen Sie:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Zum Zählen können Sie jetzt wc -l
die Anzahl der Zeilen zählen, die einer Datei oder einem Verzeichnis in der ls -1
Ausgabe entsprechen.
$ ls -1 | wc -l
6
(Beachten Sie jedoch, dass die versteckten Dateien nicht enthalten sind.)
Um entweder Dateien oder Verzeichnisse zu zählen, müssen Sie Ihre Taktik leicht ändern. In diesem Fall würde ich verwenden, ls -l
da es zeigt, was ein Verzeichnis und was eine Datei ist.
$ 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
Dann können wir grep
Verzeichnisse oder Nicht-Verzeichnisse wie folgt herausfiltern:
# 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
Verwenden Sie jetzt einfach noch wc -l
einmal, um Folgendes zu zählen:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Obwohl, können Sie vermeiden , wc
überhaupt, und die Verwendung grep
‚s -c
Option:
$ ls -l | grep -c '^d'
(Auch hier sind versteckte Dateien nicht enthalten. Beachten Sie, dass Verzeichnisse und reguläre Dateien zwei Arten von Dateien sind. Es gibt viele weitere wie Named Pipes, symbolische Links, Geräte, Sockets ...).
Wenn Sie die Dateien und Verzeichnisse rekursiv unter finden müssen, /usr/bin
möchten Sie wahrscheinlich die Taktik vollständig ändern und ein anderes Tool namens verwenden find
.
$ find /usr/bin | wc -l
4632
(obwohl über sich /usr/bin
selbst in der Zählung enthalten ist)
Die gleichen Techniken, die ich oben verwendet habe, könnten verwendet werden ls
, um etwas Ähnliches zu tun, sind jedoch ls
im Allgemeinen kein gutes Werkzeug zum Parsen der Ausgabe. find
Auf der anderen Seite wurde dafür gebaut und bietet Schalter, um entweder Dateien oder Verzeichnisse zu finden.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(Beachten Sie, dass diesmal find
versteckte Dateien enthalten sind (außer .
und ..
)).
Ich habe nie herausgefunden, warum ein Zeilenumbruchzeichen ein zulässiges Zeichen beim Erstellen von Dateinamen oder Verzeichnisnamen ist. Die oben diskutierten Methoden verwenden diese wc
und ls
würden nicht mit diesen konkurrieren. Verwenden Sie sie daher in diesem Sinne.
Erstellen Sie ein Verzeichnis und einen Dateinamen mit Zeilenumbrüchen.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
zeigt sie richtig:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Aber wc
zählt die Verzeichnisse und Dateien , die Zeilenumbrüche als 2 Elemente enthalten, nicht ein.
$ ls -1 | wc -l
10
Eine Methode, um dies zu umgehen, wenn Sie die GNU-Implementierung von verwenden, find
besteht darin, die find
Fähigkeit zu nutzen , anstelle jeder gefundenen Datei etwas anderes zu drucken und diese stattdessen zu zählen.
$ find . -printf . | wc -c
9
Hier finden wir alles im aktuellen Verzeichnis (außer ..
) und drucken jeweils einen Punkt ( .
) und zählen dann die Punkte, indem wir die wc
Fähigkeit verwenden, Bytes anstelle von Zeilen zu zählen wc -c
.
/usr/bin
alle Dateien in gut formatiert sein werden (und auch keine Leerzeichen enthalten, so dass Sie dies technisch gesehen auch nur tun können echo * | wc -w
), ist es erwähnenswert, dass all diese Dateien bei Dateinamen mit Zeilenumbrüchen beschädigt werden.
ls -l
oder ls -1
wird b / c brechen wir zählen Zeilen, keine Wörter! Das find
mag brechen, aber wir zählen wieder Zeilen, keine Wörter.
touch $'foo\nbar'
einem leeren Verzeichnis, gefolgt von einem Ihrer Befehle (z. B. ls -1 | wc -l
), werden zwei statt einer Datei gemeldet, da diese eine Datei aus zwei Zeilen wc
besteht. Es sei denn, er ls
ersetzt Zeilenumbrüche durch einen anderen Charakter (ich glaube nicht, aber ich bin momentan nicht in der Lage zu testen).
wc -c
ein Problem beim Zählen der Perioden?
Wenn Sie mit GNU eine rekursive Aufschlüsselung der Anzahl der einzelnen Dateitypen unter einem bestimmten Verzeichnis erhalten möchten find
, haben Sie folgende Möglichkeiten:
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 (&)/'
Auf /usr/bin
meinem System gibt das:
3727 regular files
710 symbolic links
Am /dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Wenn Sie Symlinks lieber als den Typ der Datei zählen möchten, auf die sie verweisen symbolic links
, können Sie sie ändern in:
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 (&)/'
Was jetzt für meine gibt /usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(Ein fehlerhafter Symlink ist ein Symlink zu einer Datei, für die find
der Typ nicht bestimmt werden kann, weil die Datei nicht vorhanden ist oder sich in einem Verzeichnis befindet, auf das Sie keinen Zugriff haben, oder weil die Auflösung des Dateipfads eine Schleife aufweist In meinem Fall sind diese 2 Symlinks zu Dateien, die jetzt weg sind.
Keiner von denen zählt .
und ..
. Wenn Sie möchten, dass sie aufgenommen werden (warum sollten Sie das find
tun ?), Gibt es keine andere Möglichkeit, als anzunehmen, dass sie für jedes Verzeichnis vorhanden sind, und sie systematisch zu zählen:
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 (&)/'
Was dann auf meinem gibt /usr/bin
:
2 directories
3727 regular files
710 symbolic links
Wenn Sie keinen Zugriff auf die GNU haben find
, können Sie die erste wie folgt umschreiben:
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
Genau genommen haben wir jetzt keine Dateien gezählt, sondern Verzeichniseinträge . Ein Verzeichnis wie dieses enthält /usr/bin
normalerweise mehrere Einträge, die auf dieselbe Datei verweisen. Zum Beispiel habe ich hier:
$ 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
Dies sind 3 Verzeichniseinträge (auch bekannt als Dateinamen oder Hardlinks) zu derselben Datei (der mit Inode 672252). Zum Zählen von Dateien anstelle von Verzeichniseinträgen und mit GNU find
und GNU uniq
(Ignorieren .
und ..
Dateien, die ohnehin Hardlinks zu anderen Verzeichnissen sind):
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 (&)/'
Auf meiner /usr/bin
gibt das:
3711 regular files
710 symbolic links
Sie haben nicht gesagt, ob Sie die gesamte Datei unter / usr / bin rekursiv oder nur unter der ersten Ebene haben möchten. Wie kommen Sie zu den Wörtern, die Sie zählen? Der übliche Weg, dies herauszufinden, besteht darin, find in wc auszuführen. So: find / usr / bin | wc -l Find listet dort alles auf, Verzeichnisse und Dateien. Wc -l zählt alle Zeilen in der Suchausgabe. Ist das eine Klassenaufgabe? Es ist in Ordnung, wenn es so ist, aber ich habe mich gefragt, warum Sie diese Informationen benötigen, damit ich die Antwort genauer anpassen kann. Bitte lassen Sie mich wissen, wenn Sie mehr benötigen. Costa
In Bash, ohne externe Werkzeuge.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
In Bash, ohne externe Tools und Rekursion.
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
.
noch ..
Einträge. Möglicherweise möchten Sie die Datei von der regulären Datei unterscheiden.