У системах (і файлових системах), що підтримують SEEK_HOLE lseekпрапор (як, наприклад, ваш Ubuntu 12.04 на ext4) і припускаючи, що значення для SEEK_HOLE4 таке, як і в 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 за те, що я звернув її до мене)