W systemach (i systemach plików) obsługujących SEEK_HOLE
lseek
flagę (takich jak Ubuntu 12.04 na ext4) i przyjmujących, że wartość SEEK_HOLE
wynosi 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 perl
i ż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 %S
zgł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_HOLE
systemu plików lub na systemach, które nie są SEEK_HOLE
zaimplementowane. 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 find
wyrażeniu rzadkości, jak na przykład 3.2e-05. Dzięki odpowiedzi @ flashydave za zwrócenie jej uwagi)