Em sistemas (e sistemas de arquivos) que suportam a SEEK_HOLE
lseek
flag (como o Ubuntu 12.04 no ext4 suportaria ) e assumindo que o valor para SEEK_HOLE
é 4, como no 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
Essa sintaxe do shell é POSIX. O material não portátil nele é perl
e aquilo SEEK_HOLE
.
lseek(SEEK_HOLE)
procura o início do primeiro furo no arquivo ou o final do arquivo se nenhum buraco for encontrado. Acima, sabemos que o arquivo não é escasso quando nos lseek(SEEK_HOLE)
leva ao final do arquivo (no mesmo local que lseek(SEEK_END)
).
Se você deseja listar os arquivos esparsos:
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}' {} +
O GNU find
(desde a versão 4.3.3) deve -printf %S
relatar a escassez de um arquivo. Ele segue a mesma abordagem da resposta de frostschutz, na medida em que leva a proporção de uso do disco e tamanho do arquivo, por isso não é garantido que todos os arquivos esparsos sejam reportados (como quando há compressão no nível do sistema de arquivos ou onde o espaço economizado pelos furos não é compensar a sobrecarga da infraestrutura do sistema de arquivos ou grandes atributos estendidos), mas funcionaria em sistemas que não possuem SEEK_HOLE
ou sistemas de arquivos onde SEEK_HOLE
não são implementados. Aqui com as ferramentas GNU:
find . -type f ! -size 0 -printf '%S:%p\0' |
awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'
(observe que uma versão anterior desta resposta não funcionou corretamente quando find
expressa a escassez como, por exemplo, 3.2e-05. Obrigado à resposta do @ flashydave por chamar a atenção)