У системах (і файлових системах), що підтримують SEEK_HOLE
lseek
прапор (як, наприклад, ваш Ubuntu 12.04 на ext4) і припускаючи, що значення для SEEK_HOLE
4 таке, як і в Linux:
if perl -le 'seek STDIN,0,4;$p=tell STDIN;
seek STDIN,0,2; exit 1 if $p == tell STDIN'< the-file; then
echo the-file is sparse
else
echo the-file is not sparse
fi
Синтаксис оболонки - POSIX. Непереносні речі в ньому є perl
і те SEEK_HOLE
.
lseek(SEEK_HOLE)
прагне до початку першого отвору у файлі, або до кінця файла, якщо жодного отвору не знайдено. Вище ми знаємо, що файл не є рідким, коли lseek(SEEK_HOLE)
веде нас до кінця файлу (до того самого місця, що і lseek(SEEK_END)
).
Якщо ви хочете перерахувати рідкі файли:
find . -type f ! -size 0 -exec perl -le 'for(@ARGV){open(A,"<",$_)or
next;seek A,0,4;$p=tell A;seek A,0,2;print if$p!=tell A;close A}' {} +
GNU find
(починаючи з версії 4.3.3) -printf %S
повинен повідомляти про розрідженість файлу. Він приймає той самий підхід, що і у відповіді frostschutz, оскільки він приймає співвідношення використання диска та розміру файлу, тому не гарантується повідомлення про всі розріджені файли (наприклад, коли відбувається стиснення на рівні файлової системи або там, де місце, збережене отворами, не має компенсувати накладні інфраструктури файлової системи або великі розширені атрибути), але вони працюватимуть у системах, які не мають SEEK_HOLE
або файлові системи там, де SEEK_HOLE
не реалізовано. Ось з інструментами GNU:
find . -type f ! -size 0 -printf '%S:%p\0' |
awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'
(зауважте, що більш рання версія цієї відповіді не працювала належним чином, коли вона find
виражала рідкість, як, наприклад, 3.2e-05. Завдяки відповіді @ flashydave за те, що я звернув її до мене)