En sistemas (y sistemas de archivos) que admiten el SEEK_HOLE lseekindicador (como lo haría su Ubuntu 12.04 en ext4) y suponiendo que el valor SEEK_HOLEes 4 como en 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
Esa sintaxis de shell es POSIX. Las cosas no portátiles que contiene son perly eso SEEK_HOLE.
lseek(SEEK_HOLE)busca el inicio del primer agujero en el archivo, o el final del archivo si no se encuentra ningún agujero. Arriba sabemos que el archivo no es escaso cuando lseek(SEEK_HOLE)nos lleva al final del archivo (al mismo lugar que lseek(SEEK_END)).
Si desea enumerar los archivos dispersos:
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}' {} +
El GNU find(desde la versión 4.3.3) tiene -printf %Sque informar la escasez de un archivo. Toma el mismo enfoque que la respuesta de frostschutz, ya que toma la proporción de uso del disco frente al tamaño del archivo, por lo que no se garantiza que informe todos los archivos dispersos (como cuando hay compresión a nivel del sistema de archivos o donde el espacio ahorrado por los agujeros no compensar la sobrecarga de la infraestructura del sistema de archivos o los grandes atributos extendidos), pero funcionaría en sistemas que no tienen SEEK_HOLEo sistemas de archivos donde SEEK_HOLEno se implementa. Aquí con las herramientas de GNU:
find . -type f ! -size 0 -printf '%S:%p\0' |
awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'
(tenga en cuenta que una versión anterior de esta respuesta no funcionó correctamente cuando findexpresó la escasez como, por ejemplo, 3.2e-05. Gracias a la respuesta de @ flashydave por llamar mi atención)