Kurze Antwort:
\ls -afq | wc -l
(Dies beinhaltet .
und ..
, also subtrahiere 2)
Wenn Sie die Dateien in einem Verzeichnis auflisten, können drei häufige Probleme auftreten:
- Auflisten der Dateinamen im Verzeichnis. Dies ist unvermeidlich: Es gibt keine Möglichkeit, die Dateien in einem Verzeichnis zu zählen, ohne sie aufzuzählen.
- Sortieren der Dateinamen. Shell Wildcards und der
ls
Befehl machen das.
- Aufruf
stat
zum Abrufen von Metadaten zu jedem Verzeichniseintrag, z. B. ob es sich um ein Verzeichnis handelt.
# 3 ist bei weitem am teuersten, da für jede Datei ein Inode geladen werden muss. Im Vergleich dazu sind alle für # 1 benötigten Dateinamen in wenigen Blöcken kompakt gespeichert. # 2 verschwendet etwas CPU-Zeit, ist aber oft kein Deal Breaker.
Wenn die Dateinamen keine Zeilenumbrüche enthalten, werden Sie durch eine einfache Angabe darüber informiert, ls -A | wc -l
wie viele Dateien sich im Verzeichnis befinden. Beachten Sie, dass, wenn Sie einen Alias für haben ls
, dies möglicherweise einen Aufruf von auslösen kann stat
(z. B. ls --color
oder ls -F
den Dateityp kennen müssen, für den ein Aufruf erforderlich ist stat
), also von der Befehlszeile aus, command ls -A | wc -l
oder \ls -A | wc -l
um einen Alias zu vermeiden.
Wenn der Dateiname Zeilenumbrüche enthält, hängt es von der Unix-Variante ab, ob Zeilenumbrüche aufgelistet werden oder nicht. GNU coreutils und BusyBox werden standardmäßig ?
für eine neue Zeile angezeigt, damit sie sicher sind.
Rufen Sie ls -f
an, um die Einträge aufzulisten, ohne sie zu sortieren (Nr. 2). Dies schaltet sich automatisch ein -a
(zumindest bei modernen Systemen). Die -f
Option ist in POSIX, aber mit optionalem Status. Die meisten Implementierungen unterstützen dies, BusyBox jedoch nicht. Die Option -q
ersetzt nicht druckbare Zeichen einschließlich Zeilenumbrüchen durch ?
; Es ist POSIX, wird jedoch von BusyBox nicht unterstützt. Lassen Sie es daher aus, wenn Sie BusyBox-Unterstützung benötigen, und zahlen Sie dabei zu viele Dateien, deren Name ein Zeilenumbruchzeichen enthält.
Wenn das Verzeichnis keine Unterverzeichnisse enthält, find
werden stat
die Einträge in den meisten Versionen von nicht abgerufen (Blattverzeichnisoptimierung: Ein Verzeichnis mit einer Linkanzahl von 2 kann keine Unterverzeichnisse enthalten. Daher find
müssen die Metadaten der Einträge nur nachgeschlagen werden, wenn ein Bedingung wie es -type
erforderlich ist). Dies find . | wc -l
ist eine tragbare und schnelle Methode zum Zählen von Dateien in einem Verzeichnis, vorausgesetzt, das Verzeichnis enthält keine Unterverzeichnisse und kein Dateiname enthält eine neue Zeile.
Wenn das Verzeichnis keine Unterverzeichnisse enthält, die Dateinamen jedoch möglicherweise Zeilenumbrüche enthalten, probieren Sie eines dieser Verzeichnisse aus (das zweite sollte schneller sein, wenn es unterstützt wird, dies ist jedoch möglicherweise nicht erkennbar).
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
Auf der anderen Seite, verwenden Sie nicht , find
wenn das Verzeichnis Verzeichnisse hat: auch find . -maxdepth 1
Anrufe stat
auf jedem Eintrag (zumindest mit GNU finden und BusyBox zu finden). Sie vermeiden das Sortieren (Nr. 2), zahlen jedoch den Preis für eine Inode-Suche (Nr. 3), die die Leistung beeinträchtigt.
In der Shell ohne externe Tools können Sie die Dateien im aktuellen Verzeichnis mit zählen set -- *; echo $#
. Dadurch werden Punktdateien (Dateien, deren Name mit " .
1" beginnt ) übersehen und in einem leeren Verzeichnis wird "1" anstelle von "0" angezeigt. Dies ist der schnellste Weg, um Dateien in kleinen Verzeichnissen zu zählen, da kein externes Programm gestartet werden muss, aber (mit Ausnahme von zsh) Zeit für größere Verzeichnisse aufgrund des Sortierschritts (# 2) verschwendet wird.
In Bash ist dies eine zuverlässige Methode, um die Dateien im aktuellen Verzeichnis zu zählen:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
In ksh93 ist dies eine zuverlässige Methode, um die Dateien im aktuellen Verzeichnis zu zählen:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
In zsh ist dies eine zuverlässige Methode, um die Dateien im aktuellen Verzeichnis zu zählen:
a=(*(DNoN))
echo $#a
Wenn Sie die haben mark_dirs
Option gesetzt, stellen Sie sicher, um sie auszuschalten: a=(*(DNoN^M))
.
In jeder POSIX-Shell ist dies eine zuverlässige Methode, um die Dateien im aktuellen Verzeichnis zu zählen:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
Alle diese Methoden sortieren die Dateinamen mit Ausnahme der zsh-Methode.
ls -l|wc -l
wäre wegen der Gesamtanzahl der Blöcke in der erstenls -l
Ausgabezeile um eins gesperrt