En sistemas (y sistemas de archivos) que admiten el SEEK_HOLE
lseek
indicador (como lo haría su Ubuntu 12.04 en ext4) y suponiendo que el valor SEEK_HOLE
es 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 perl
y 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 %S
que 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_HOLE
o sistemas de archivos donde SEEK_HOLE
no 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 find
expresó la escasez como, por ejemplo, 3.2e-05. Gracias a la respuesta de @ flashydave por llamar mi atención)