Byteanzahl von "ls -l <zufällige Datei>" im Vergleich zu "wc -c <zufällige Datei>"

25

Gibt es eine mögliche Situation, wenn

ls -l file.txt

zeigt nicht die gleiche Anzahl von Bytes an wie

wc -c file.txt

In einem Skript habe ich einen Vergleich dieser beiden Werte gefunden. Was könnte der Grund dafür sein? Ist es überhaupt möglich, dass dieselbe Datei unterschiedliche Bytezahlen hat?

Rokas.ma
quelle
2
Könnten Sie diesem Skript, das Sie gefunden haben, einen Kontext geben?
Kusalananda
Siehe auch unix.stackexchange.com/a/321502/22565
Stéphane Chazelas

Antworten:

13

Ja, es gibt solche Fälle.

Im Fall von Symlinks auf Linux - System mit GNU ls, die ls -ldie Größe der Verbindung löschen, während wc -cdie tatsächliche Datei und liest Anzahl von Bytes , die dort zu lösen. Unten sehen Sie, dass ls -l29 Bytes gemeldet werden, während wcdie aktuelle Datei 172 Bytes enthält.

$ ls -l /etc/resolv.conf                                                                                                 
lrwxrwxrwx 1 root root 29 1月  17  2016 /etc/resolv.conf -> ../run/resolvconf/resolv.conf
$ wc -c /etc/resolv.conf                                                                                                 
172 /etc/resolv.conf
$ wc -c /var/run/resolvconf/resolv.conf                                                                                  
172 /var/run/resolvconf/resolv.conf
$ ls -l /var/run/resolvconf/resolv.conf                                                                                  
-rw-r--r-- 1 root root 172 1月  15 15:49 /var/run/resolvconf/resolv.conf

Im Fall eines virtuellen Dateisysteme , wie/proc oder /sys, werden viele Dateien dort zeigen , wie Größe 0 mit ls -l. Unter /devDateisystem haben wir eine Vielzahl von speziellen Dateien, wie Zeichengeräte und Blockgeräte - wc -chängt an diesen und ls -lzeigt statt der Größe Haupt- und Nebenzahlen an.

Named Pipes werden als 0Bytes von gemeldet ls -c, wc -clesen jedoch tatsächlich den Inhalt der Pipe. Technisch wird Ihnen also mitgeteilt , wie viele Daten sich in der Named Pipes befinden :

$ mkfifo named.pipe                                                                                                      
$ echo "This is a test" > named.pipe &
[1] 2129
$ ls -l named.pipe
prw-rw-r-- 1 xieerqi xieerqi 0 1月  16 08:40 named.pipe|
$ wc -c named.pipe
15 named.pipe
[1] + Done                 echo "This is a test" >named.pipe 

Bei normalen Dateien sollte die Größe gleich sein.


Der Sinn von ls -lund wc -cund wie sie funktionieren ist ebenfalls unterschiedlich. wc -cTatsächlich öffnet sich die Datei zum Lesen (Sie können das sehen, wenn Sie strace wc -c /etc/passwdzum Beispiel ausführen ). ls -lführt nur einen stat()Anruf auf diesen durch. Dies erklärt auch, warum in /proc ls -lShows der Größe 0 diese Dateien nicht angegeben werden können, da sie nicht "echt" oder tatsächlich auf der Festplatte / ssd gespeichert sind. wc -cLiest stattdessen den Inhalt dieser Datei und berechnet ihre Größe.

Schließlich ls -list nur ein Tool zum interaktiven Auflisten von Elementen. Es ist selten gut für Skripte geeignet. Wenn Sie die Daten tatsächlich lesen müssen, verwenden Sie wc -cstattdessen.

Bitte beachten Sie, dass für die Skripterstellung und die Größenbestimmung einer Datei lsnicht der beste Kandidat ist. Tatsächlich ist es eine der gebräuchlichsten Methoden, das Parsen von lsAusgaben zu vermeiden . Bitte verwenden Sie du -b , um die Größe einer Datei zu ermitteln.

Sergiy Kolodyazhnyy
quelle
1
Eine kleine Klarstellung - virtuelle Dateien (in /sys/, /proc/usw.) könnenstat Informationen liefern , wenn der Implementierer dies wünscht. Die meiste Zeit gibt es keinen zwingenden Grund dafür, so dass es weggelassen wird. Zu den Beispielen gehört, /proc/kcorewelche als Größe des adressierbaren Kernelspeichers angegeben wird (normalerweise viel mehr als der verfügbare physische Speicher).
Toby Speight
11

ls -l Gibt die Größe der vom Dateisystem gemeldeten Datei zurück.

wc -cversucht, die Datei zu lesen, um die tatsächliche Größe zu ermitteln. Nach meinen Beobachtungen scheint es, als würde man zuerst versuchen, bis zum Ende zu suchen. Wenn dies nicht funktioniert, wird die gesamte Datei ausgelesen, wobei die Größe mitgezählt wird.

Dies ist eine einfache Beschreibung der Funktionsweise der beiden Tools, die jedoch eine Reihe von Auswirkungen auf die Ergebnisse hat:

lsgibt für bestimmte Dateisysteme eine falsche Ausgabe aus. Beispielsweise geben virtualisierte Dateisysteme wie beispielsweise /procfür viele Dateien eine Größe von Null an, da diese "Dateien" nirgendwo physisch gespeichert sind. Sie werden nach Bedarf von der Software generiert.

wcfunktioniert überhaupt nicht für Dateien ohne Leseberechtigungen, während lsnur Berechtigungen zum Auflisten des Verzeichnisses erforderlich sind (vergleichen ls -l /etc/shadowmit wc -c /etc/shadow).

Wie in anderen Antworten erwähnt, unterscheidet sich auch das Verhalten für symbolische Verknüpfungen. Da wcversucht wird, sie zu lesen, wird die Datei gelesen, auf die der Symlink verweist. Da jedoch lsnur das Dateisystem abgefragt wird, wird die Größe angegeben, die zum Speichern des symbolischen Links verwendet wird.

Ich bin mir sicher, dass es andere Unterschiede gibt, an die ich noch nicht gedacht habe, aber ich dachte, ich würde eine klare und einfache Erklärung für den Grund hinter diesen Unterschieden geben.

Muzer
quelle
+1 für das Erwähnen von Leseberechtigungen und seek(). Dies scheint der Fall zu sein, nachdem strace wc -leinige große Dateien ausgeführt wurden.
Sergiy Kolodyazhnyy
+1 für das Hinzufügen von viel mehr Details als meine Antwort!
Cyclic3
6

Für eine normale Datei rufen ls und wc stat auf. Für eine Datei von / proc oder / sys gibt ls 0 zurück, wc jedoch eine andere Zahl:

$ ls -l /proc/modules
-r--r--r--  1 root root 0 Jan 16 14:56 modules
                        ^ this one
$ wc -c /proc/modules
7621 modules

Dies ist wahrscheinlich eine Möglichkeit herauszufinden, ob es sich bei etwas um eine spezielle Datei handelt.

Cyclic3
quelle
2
wc -cfür mich heißt das zumindest fstat, aber scheinbar für andere zwecke. Es findet die Länge der Datei lseekbis zum Ende. Für den Fall, dass dies einen Fehler zurückgibt, handelt es sich um readdie gesamte Datei.
Muzer