Чи можлива ситуація, коли
ls -l file.txt
показує не таку кількість байтів, як
wc -c file.txt
В одному сценарії я знайшов порівняння цих двох значень. Що може бути причиною цього? Чи навіть можливо мати різні підрахунки байтів одного файлу?
Чи можлива ситуація, коли
ls -l file.txt
показує не таку кількість байтів, як
wc -c file.txt
В одному сценарії я знайшов порівняння цих двох значень. Що може бути причиною цього? Чи навіть можливо мати різні підрахунки байтів одного файлу?
Відповіді:
Так, бувають такі випадки.
У разі посилань на Linux із системою GNU ls
, ls -l
волю видасть розмір посилання, при wc -c
цьому вирішить фактичний файл та прочитає там кількість байтів. Нижче ви бачите, що ls -l
повідомляє 29 байт, а wc
172 байти у фактичному файлі.
$ 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
У випадку віртуальних файлових систем , таких як/proc
або /sys
, багато файлів відображатимуться як розмір 0 ls -l
. Під /dev
файловою системою ми маємо різноманітні спеціальні файли, такі як символьні пристрої та блокові пристрої - wc -c
висить на них і ls -l
показує основні та незначні числа замість розміру.
Іменовані труби будуть повідомлятися як 0
байти ls -c
, але wc -c
фактично будуть читати вміст труби, тому технічно він скаже вам, скільки даних міститься в названій трубі:
$ 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
Для звичайних файлів розмір повинен бути рівним.
Сенс ls -l
і wc -c
, і як вони працюють також відрізняється. wc -c
насправді відкривається файл для читання (ви можете побачити це, якщо, наприклад, запустите strace wc -c /etc/passwd
). ls -l
виконує stat()
дзвінок лише з тих. Це також пояснює, чому в /proc
ls -l
шоу 0 розмір - ви не можете статистика цих файлів, оскільки вони не "справжні" або фактично зберігаються на жорсткому диску / ssd. wc -c
натомість читає вміст цього файлу та обчислює його розмір.
Нарешті, ls -l
це лише інструмент для інтерактивного переліку елементів. Це рідко підходить для сценаріїв. Коли вам справді потрібно прочитати дані, скористайтеся wc -c
натомість.
Зауважте, що сценарій та оцінка розміру файлу ls
- не найкращий кандидат. Насправді, це одна з поширених практик уникнути розбору ls
результатів . Будь ласка, використовуйте du -b
для з’ясування розміру файлу.
/sys/
, /proc/
тощо) можуть надавати stat
інформацію, якщо реалізатор захоче. Здебільшого це не є вагомою причиною, тому це опущено. Приклади включають, /proc/kcore
що повідомляється як розмір пам'яті ядра, що адресоване (зазвичай набагато більше, ніж наявна фізична пам'ять).
ls -l
поверне розмір файлу, про який повідомляє файлова система.
wc -c
спробує прочитати файл, щоб визначити "фактичний" розмір. З моїх спостережень, схоже, спершу намагаюся шукати до кінця, і якщо це не спрацює, він зчитує весь файл, рахуючи розмір, який він проходить.
Це простий опис того, що два інструменти роблять, але це призводить до низки наслідків для результатів:
ls
дасть неправильний вихід для певних файлових систем. Наприклад, віртуалізовані файлові системи, як-от /proc
, повідомлять розмір нуля для багатьох файлів, оскільки ці "файли" фізично ніде не зберігаються; вони генеруються відповідно до вимог програмного забезпечення.
wc
не працюватиме на всіх для файлів без дозволу на читання, а ls
вимагають дозволів тільки для відображення каталогу (порівняйте ls -l /etc/shadow
з wc -c /etc/shadow
).
Як згадується в інших відповідях, поведінка для символічних посилань також відрізняється. Оскільки він wc
намагається їх прочитати, він закінчує читання файлу, на який вказує символьне посилання, тоді як, оскільки ls
просто запитує файлову систему, він повідомляє розмір, який використовується для зберігання символічного посилання.
Я впевнений, що є інші відмінності, про які я ще не думав, але я подумав, що я дам чітке і просте пояснення щодо основної причини цих відмінностей.
seek()
. Це, мабуть, так, після запуску strace wc -l
декількох великих файлів.
Для звичайного файлу ls та wc стат. Однак для файлу / proc або / sys, ls повертає 0, але wc повертає інше число:
$ ls -l /proc/modules
-r--r--r-- 1 root root 0 Jan 16 14:56 modules
^ this one
$ wc -c /proc/modules
7621 modules
Це, мабуть, якийсь спосіб з’ясувати, чи є щось спеціальним файлом.
wc -c
для мене принаймні дзвонить fstat
, але, здавалося б, для інших цілей. Він знаходить довжину файлу, lseek
відкладаючи його до кінця. Якщо це поверне помилку, це read
весь файл.