W systemach (i systemach plików) obsługujących SEEK_HOLE lseekflagę (takich jak Ubuntu 12.04 na ext4) i przyjmujących, że wartość SEEK_HOLEwynosi 4 tak jak w Linuksie:
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
Ta składnia powłoki to POSIX. Non-przenośny rzeczy są w niej perli że SEEK_HOLE.
lseek(SEEK_HOLE)szuka początku pierwszego otworu w pliku lub końca pliku, jeśli nie znaleziono otworu. Powyżej wiemy, że plik nie jest rzadki, gdy lseek(SEEK_HOLE)przenosi nas na koniec pliku (w to samo miejsce, co lseek(SEEK_END)).
Jeśli chcesz wyświetlić listę rzadkich plików:
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(od wersji 4.3.3) musi -printf %Szgłaszać rzadkość pliku. Przyjmuje to samo podejście, co odpowiedź frostschutza , ponieważ przyjmuje stosunek wykorzystania dysku do wielkości pliku, więc nie ma gwarancji zgłaszania wszystkich plików rzadkich (na przykład, gdy istnieje kompresja na poziomie systemu plików lub gdy miejsce zaoszczędzone przez dziury nie kompensować narzut infrastruktury infrastruktury plików lub duże rozszerzone atrybuty), ale działałby na systemach, które nie mają SEEK_HOLEsystemu plików lub na systemach, które nie są SEEK_HOLEzaimplementowane. Tutaj z narzędziami GNU:
find . -type f ! -size 0 -printf '%S:%p\0' |
awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'
(zauważ, że wcześniejsza wersja tej odpowiedzi nie działała poprawnie po findwyrażeniu rzadkości, jak na przykład 3.2e-05. Dzięki odpowiedzi @ flashydave za zwrócenie jej uwagi)