Die 12Sie sehen , ist nicht die Anzahl der Dateien, aber die Anzahl der Plattenblöcke verbraucht.
Von info coreutils 'ls invocation':
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
Die Summe geht von 12bis, 20wenn Sie ls -laanstelle von verwenden, ls -lweil Sie zwei zusätzliche Verzeichnisse zählen: .und ... Sie verwenden vier Plattenblöcke für jedes (leere) Verzeichnis, sodass Ihre Gesamtzahl von 3 × 4 auf 5 × 4 steigt. (Höchstwahrscheinlich verwenden Sie einen Plattenblock von 4096 Bytes für jedes Verzeichnis, wie die infoSeite zeigt, die Dienstprogramm überprüft das Festplattenformat nicht, geht jedoch von einer Blockgröße von aus, 1024sofern nicht anders angegeben.)
Wenn Sie einfach die Anzahl der Dateien abrufen möchten, können Sie etwas wie versuchen
ls | wc -lschlägt fehl, wenn der Dateiname Dateien mit einer neuen Zeile enthält. Dies ist widerstandsfähiger:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
Flimm
20
"Wenn Dateinamen eine neue Zeile enthalten" ... schaudert
Petah
8
Wie man lsSie sehen, können Sie Steuerzeichen vermeiden, indem Sie -b(sie maskieren) oder -q(sie weglassen). So zum Zählen, ls -1q | wc -list sicher und genau zum Anzeigen von nicht versteckten Dateien. ls -1qA | wc -lversteckte Dateien zu zählen (aber nicht .und ..). Ich benutze -1stattdessen, -lweil das schneller sein sollte.
Oli
18
user4556274 hat das warum bereits beantwortet . Meine Antwort dient nur dazu, zusätzliche Informationen darüber, wie richtig Dateien zählen zu.
In der Unix-Community herrschtls allgemeiner Konsens darüber, dass das Parsen der Ausgabe eine sehr, sehr schlechte Idee ist , da Dateinamen Steuerzeichen oder versteckte Zeichen enthalten können. Aufgrund eines Zeilenumbruchs in einem Dateinamen müssen wir uns beispielsweise ls | wc -lmitteilen, dass die Ausgabe von 5 Zeilen enthält ls(was auch der Fall ist), in Wirklichkeit befinden sich jedoch nur 4 Dateien im Verzeichnis.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Methode 1: finden Sie Dienstprogramm
Der findBefehl, der normalerweise zum Analysieren von Dateinamen verwendet wird, kann uns hier helfen, indem er die Inode-Nummer ausgibt . Sei es ein Verzeichnis oder eine Datei, es hat nur eine einzige Inode-Nummer. Durch die Verwendung -printf "%i\n"und den Ausschluss von .via können -not -name "."wir die Dateien genau zählen. (Beachten Sie die Verwendung von -maxdepth 1, um ein rekursives Absteigen in Unterverzeichnisse zu verhindern.)
setBefehl wird verwendet, um Positionsparameter der Shell festzulegen (die $<INTEGER>Variablen, wie in echo $1). Dies wird häufig verwendet, um die /bin/shBegrenzung fehlender Arrays zu umgehen. Eine Version, die zusätzliche Prüfungen durchführt, finden Sie in Gilles Antwort unter Unix & Linux.
In Shells, die Arrays unterstützen, wie bashwir sie verwenden können
Ein ähnlicher Trick wie bei der findMethode "which used" wcund "globstar" kann statzum Zählen der Inode-Nummern pro Zeile verwendet werden:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Ein alternativer Ansatz ist die Verwendung eines Platzhalters in einer forSchleife. (Beachten Sie, dass dieser Test ein anderes Verzeichnis verwendet, um zu testen, ob dieser Ansatz in Unterverzeichnisse abfällt, was nicht der Fall ist. 16 ist die überprüfte Anzahl von Elementen in my. ~/bin)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Methode 3: Andere Sprachen / Dolmetscher
Python kann auch mit problematischen Dateinamen umgehen, indem es die Länge einer Liste in Anbetracht meiner os.listdir()Funktion ausgibt (was nicht rekursiv ist und nur Elemente in dem als Argument angegebenen Verzeichnis auflistet).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
In Bash wäre eine andere Option, ein Array zu verwenden, z. B. items=( dir/* ); echo ${#items[@]}(Hinzufügen shopt -s dotglob, um versteckte Dateien einzuschließen).
Steeldriver
1
Das Drucken von Inode-Nummern erleichtert das Filtern von Hardlinks, falls gewünscht, mit find | sort -u | wc -l.
Peter Cordes
@steeldriver: Ich denke, dass die Bash-Array-Methode wahrscheinlich nicht schneller ist. Wenn Sie möchten, dass es rekursiv ist, müssen Sie items=( dir/** )(with shopt -s globstar) verwenden, aber bash nutzt keine zusätzlichen Metadaten aus readdir aus, sodass in jedem Verzeichniseintrag angegeben wird, ob es sich um ein Verzeichnis selbst handelt. Viele Dateisysteme speichern den Dateityp im Verzeichniseintrag, sodass readdir ihn zurückgeben kann, ohne auf die Inodes zuzugreifen. (ZB hat dies das neueste nicht standardmäßige XFS, und ich denke, ext4 hat es länger.) Wenn Sie stracefeststellen, werden Sie viel weniger statSystemaufrufe sehen als wenn Sie bash stracen.
Peter Cordes
2
Warum nicht einfach benutzen print(len(os.listdir('.')))? Es müssen weniger Zeichen eingegeben werden, und der Zugriff auf doppelt unterstrichene Attribute wird vermieden.
ls | wc -l
schlägt fehl, wenn der Dateiname Dateien mit einer neuen Zeile enthält. Dies ist widerstandsfähiger:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
man ls
Sie sehen, können Sie Steuerzeichen vermeiden, indem Sie-b
(sie maskieren) oder-q
(sie weglassen). So zum Zählen,ls -1q | wc -l
ist sicher und genau zum Anzeigen von nicht versteckten Dateien.ls -1qA | wc -l
versteckte Dateien zu zählen (aber nicht.
und..
). Ich benutze-1
stattdessen,-l
weil das schneller sein sollte.user4556274 hat das warum bereits beantwortet . Meine Antwort dient nur dazu, zusätzliche Informationen darüber, wie richtig Dateien zählen zu.
In der Unix-Community herrscht
ls
allgemeiner Konsens darüber, dass das Parsen der Ausgabe eine sehr, sehr schlechte Idee ist , da Dateinamen Steuerzeichen oder versteckte Zeichen enthalten können. Aufgrund eines Zeilenumbruchs in einem Dateinamen müssen wir uns beispielsweisels | wc -l
mitteilen, dass die Ausgabe von 5 Zeilen enthältls
(was auch der Fall ist), in Wirklichkeit befinden sich jedoch nur 4 Dateien im Verzeichnis.Methode 1: finden Sie Dienstprogramm
Der
find
Befehl, der normalerweise zum Analysieren von Dateinamen verwendet wird, kann uns hier helfen, indem er die Inode-Nummer ausgibt . Sei es ein Verzeichnis oder eine Datei, es hat nur eine einzige Inode-Nummer. Durch die Verwendung-printf "%i\n"
und den Ausschluss von.
via können-not -name "."
wir die Dateien genau zählen. (Beachten Sie die Verwendung von-maxdepth 1
, um ein rekursives Absteigen in Unterverzeichnisse zu verhindern.)Methode 2: Globstar
Einfach, schnell und meistens portabel:
set
Befehl wird verwendet, um Positionsparameter der Shell festzulegen (die$<INTEGER>
Variablen, wie inecho $1
). Dies wird häufig verwendet, um die/bin/sh
Begrenzung fehlender Arrays zu umgehen. Eine Version, die zusätzliche Prüfungen durchführt, finden Sie in Gilles Antwort unter Unix & Linux.In Shells, die Arrays unterstützen, wie
bash
wir sie verwenden könnenwie von steeldriver in den Kommentaren vorgeschlagen .
Ein ähnlicher Trick wie bei der
find
Methode "which used"wc
und "globstar" kannstat
zum Zählen der Inode-Nummern pro Zeile verwendet werden:Ein alternativer Ansatz ist die Verwendung eines Platzhalters in einer
for
Schleife. (Beachten Sie, dass dieser Test ein anderes Verzeichnis verwendet, um zu testen, ob dieser Ansatz in Unterverzeichnisse abfällt, was nicht der Fall ist. 16 ist die überprüfte Anzahl von Elementen in my.~/bin
)Methode 3: Andere Sprachen / Dolmetscher
Python kann auch mit problematischen Dateinamen umgehen, indem es die Länge einer Liste in Anbetracht meiner
os.listdir()
Funktion ausgibt (was nicht rekursiv ist und nur Elemente in dem als Argument angegebenen Verzeichnis auflistet).Siehe auch
quelle
items=( dir/* ); echo ${#items[@]}
(Hinzufügenshopt -s dotglob
, um versteckte Dateien einzuschließen).find | sort -u | wc -l
.items=( dir/** )
(withshopt -s globstar
) verwenden, aber bash nutzt keine zusätzlichen Metadaten aus readdir aus, sodass in jedem Verzeichniseintrag angegeben wird, ob es sich um ein Verzeichnis selbst handelt. Viele Dateisysteme speichern den Dateityp im Verzeichniseintrag, sodass readdir ihn zurückgeben kann, ohne auf die Inodes zuzugreifen. (ZB hat dies das neueste nicht standardmäßige XFS, und ich denke, ext4 hat es länger.) Wenn Siestrace
feststellen, werden Sie viel wenigerstat
Systemaufrufe sehen als wenn Sie bash stracen.print(len(os.listdir('.')))
? Es müssen weniger Zeichen eingegeben werden, und der Zugriff auf doppelt unterstrichene Attribute wird vermieden.