Liczba bajtów „ls -l <losowy plik>” w porównaniu z liczbą „wc -c <losowy plik>”

25

Czy jest jakaś możliwa sytuacja, kiedy

ls -l file.txt

pokazuje inną liczbę bajtów niż

wc -c file.txt

W jednym skrypcie znalazłem porównanie tych dwóch wartości. Co może być tego przyczyną? Czy to możliwe, aby mieć różne liczby bajtów tego samego pliku?

Rokas.ma
źródło
2
Czy możesz podać kontekst temu skryptowi, który znalazłeś?
Kusalananda
Zobacz także unix.stackexchange.com/a/321502/22565
Stéphane Chazelas

Odpowiedzi:

13

Tak, są takie przypadki.

W przypadku dowiązań symbolicznych w systemie Linux z GNU ls, ls -lwypisze rozmiar łącza, a jednocześnie wc -crozwiąże rzeczywisty plik i odczyta tam liczbę bajtów. Poniżej widać, że ls -lraportuje 29 bajtów, podczas gdy wcraportuje 172 bajty w rzeczywistym pliku.

$ 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

W przypadku wirtualnych systemów plików , takich jak/proc lub /sys, wiele plików będzie miało rozmiar 0 ls -l. W /devsystemie plików mamy wiele specjalnych plików, takich jak urządzenia znakowe i urządzenia blokowe - wc -czawiesza się na nich i ls -lpokazuje większe i mniejsze liczby zamiast wielkości.

Nazwane potoki będą zgłaszane jako 0bajty przez ls -c, ale w wc -crzeczywistości odczytują zawartość potoku, więc technicznie powie ci, ile danych jest w nazwanym potoku:

$ 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 

W przypadku zwykłych plików rozmiar powinien być równy.


Punkt ls -la wc -c, i jak one działają także różni. wc -cfaktycznie otwiera plik do odczytu (możesz to zobaczyć, jeśli uruchomisz strace wc -c /etc/passwdna przykład). ls -lwykonuje tylko stat()połączenia na tych. Wyjaśnia to również, dlaczego w /proc ls -lprogramach pokazuje rozmiar 0 - nie można statystyki tych plików, ponieważ nie są one „prawdziwe” lub faktycznie przechowywane na dysku twardym / ssd. wc -czamiast tego odczytuje zawartość tego pliku i oblicza jego rozmiar.

Wreszcie ls -ljest tylko narzędziem do interaktywnego wyświetlania pozycji. Rzadko nadaje się do pisania skryptów. Gdy rzeczywiście potrzebujesz odczytać dane, użyj wc -czamiast tego.

Należy pamiętać, że do pisania skryptów i oceny rozmiaru pliku lsnie jest najlepszym kandydatem. W rzeczywistości jest to jedna z powszechnych praktyk unikania analizowania lswyników . Użyj, du -b aby sprawdzić rozmiar pliku.

Sergiy Kolodyazhnyy
źródło
1
Małe wyjaśnienie - pliki wirtualne (w /sys/, /proc/itp.) Mogą dostarczyć statinformacji, jeśli realizator zdecyduje się na to. Przez większość czasu nie ma ważnego powodu, więc zostało to pominięte. Przykłady obejmują, /proc/kcorektóra jest zgłaszana jako rozmiar adresowalnej pamięci jądra (zwykle znacznie więcej niż dostępna pamięć fizyczna).
Toby Speight
11

ls -l zwróci rozmiar pliku zgłaszanego przez system plików.

wc -cspróbuje odczytać plik, aby określić „rzeczywisty” rozmiar. Z moich obserwacji wynika, że ​​najpierw próbuję szukać do końca, a jeśli to nie zadziała, odczyta cały plik, licząc rozmiar w miarę upływu czasu.

Jest to prosty opis tego, co robią te dwa narzędzia, ale prowadzi do szeregu implikacji dla wyników:

lsda niepoprawne wyjście dla niektórych systemów plików. Na przykład zwirtualizowane systemy plików, takie jak, /procbędą zgłaszać rozmiar zero dla wielu plików, ponieważ te „pliki” nigdzie nie są fizycznie przechowywane; są generowane zgodnie z wymaganiami oprogramowania.

wcnie będzie w ogóle działać w przypadku plików bez uprawnień do odczytu, ale lswymaga tylko uprawnień do wyświetlenia katalogu (porównaj ls -l /etc/shadowz wc -c /etc/shadow).

Jak wspomniano w innych odpowiedziach, zachowanie linków symbolicznych jest również inne. Ponieważ wcpróbuje je odczytać, kończy się odczytaniem pliku, do którego wskazuje dowiązanie symboliczne, a ponieważ lspo prostu odpytuje system plików, zgłosi rozmiar użyty do przechowywania samego dowiązania symbolicznego.

Jestem pewien, że istnieją jeszcze inne różnice, o których jeszcze nie pomyślałem, ale pomyślałem, że podam jasne i proste wyjaśnienie podstawowego powodu tych różnic.

Muzer
źródło
+1 za wzmiankę o uprawnieniach do odczytu i seek(). Wydaje się, że tak jest po uruchomieniu strace wc -lna kilku dużych plikach.
Sergiy Kolodyazhnyy
+1 za dodanie znacznie więcej szczegółów niż moja odpowiedź!
Cyclic3
6

Dla normalnego pliku, statystyki wywołań ls i wc. Jednak dla pliku / proc lub / sys ls zwraca 0, ale wc zwraca inną liczbę:

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

Jest to prawdopodobnie sposób na sprawdzenie, czy coś jest plikiem specjalnym.

Cykliczny 3
źródło
2
wc -cdla mnie przynajmniej dzwoni fstat, ale pozornie do innych celów. Znajduje długość pliku, lseekdocierając do końca. W przypadku, gdy zwraca błąd, readjest to cały plik.
Muzer