¿Se puede volver a dispersar un archivo que originalmente era escaso y luego expandido?

29

Sé que copiar o transferir lo que originalmente era un archivo disperso sin usar una utilidad que comprenda los archivos dispersos hará que se llenen los 'agujeros'. ¿Hay algún método o utilidad para convertir lo que alguna vez fue un archivo disperso de nuevo en disperso?

Por ejemplo:
crear archivo disperso:

% dd if=/dev/zero of=TEST bs=1 count=0 seek=1G
# do some op that pads out the holes
% scp TEST localhost:~/TEST2
% ls -lhs TEST*
   0 -rw-rw-r--. 1 tony tony 1.0G Oct 16 13:35 TEST
1.1G -rw-rw-r--. 1 tony tony 1.0G Oct 16 13:37 TEST2

¿Hay alguna manera de:

% resparse TEST2
to get:
   0 -rw-rw-r--. 1 tony tony 1.0G Oct 16 13:35 TEST
  0G -rw-rw-r--. 1 tony tony 1.0G Oct 16 13:37 TEST2
usuario25849
fuente
Lo siento, tuve que arreglar las
preguntas
1
Lo único que puede hacer esto de todo lo que he visto es un 'cp' de GNU, como en '% cp --sparse = siempre antes-sparse-file recientemente-sparse-file' El detractor es que no lo hará ' en su lugar'.
user25849
Si desea copiar un archivo disperso y dejar que la copia sea dispersa, use rsync -aS.
Gilles 'SO- deja de ser malvado'

Respuestas:

30

Editar 2015

a partir de util-linux 2.25, la fallocateutilidad en Linux tiene una opción -d/ --dig-holepara eso.

fallocate -d the-file

Cavaría un hoyo por cada bloque lleno de ceros en el archivo


En sistemas más antiguos, puede hacerlo a mano:

Linux tiene una FALLOC_FL_PUNCH_HOLEopción fallocateque puede hacer esto. Encontré un script en github con un ejemplo:

Usando FALLOC_FL_PUNCH_HOLE de Python

Lo modifiqué un poco para hacer lo que pediste: perforar agujeros en regiones de archivos que están llenos de ceros. Aquí está:

Usando FALLOC_FL_PUNCH_HOLE de Python para hacer agujeros en los archivos

usage: punch.py [-h] [-v VERBOSE] FILE [FILE ...]

Punch out the empty areas in a file, making it sparse

positional arguments:
  FILE                  file(s) to modify in-place

optional arguments:
  -h, --help            show this help message and exit
  -v VERBOSE, --verbose VERBOSE
                        be verbose

Ejemplo:

# create a file with some data, a hole, and some more data
$ dd if=/dev/urandom of=test1 bs=4096 count=1 seek=0
$ dd if=/dev/urandom of=test1 bs=4096 count=1 seek=2

# see that it has holes
$ du --block-size=1 --apparent-size test1
12288   test1
$ du --block-size=1 test1
8192    test1

# copy it, ignoring the hole
$ cat test1 > test2
$ du --block-size=1 --apparent-size test2
12288   test2
$ du --block-size=1 test2
12288    test2

# punch holes again
$ ./punch.py test2
$ du --block-size=1 --apparent-size test2
12288   test2
$ du --block-size=1 test2
8192    test2

# verify
$ cmp test1 test2 && echo "files are the same"
files are the same

Tenga en cuenta que punch.pysolo encuentra bloques de 4096 bytes para perforar, por lo que es posible que no haga que un archivo sea tan escaso como cuando comenzó. Podría hacerse más inteligente, por supuesto. Además, solo está ligeramente probado , así que tenga cuidado y haga copias de seguridad antes de confiar en él.

Jim Paris
fuente
1
Esto me gusta más porque no requiere reescribir todo el archivo nuevamente.
Peter
8

Si desea que un archivo sea escaso, puede hacerlo directamente con dd.

dd if=./zeropadded.iso of=./isnowsparse.iso conv=sparse

Del dd(1)manual:

          sparse   If one or more output blocks would consist solely of
                   NUL bytes, try to seek the output file by the required
                   space instead of filling them with NULs, resulting in a
                   sparse file.

Entonces, tenga en cuenta que buscará hacia adelante solo si todo el bloque está vacío. Para un uso máximo de escasez bs=1.

bahamat
fuente
2
Cualquier tamaño de bloque menor que bs=512realmente no tiene sentido, ya que los discos son dispositivos de bloque. ( bs=4096en unidades más nuevas)
lapo
parece que esto es equivalente acp --sparse=always zeropadded.iso isnowsparse.iso
maxschlepzig
2

A menos que lo taractive con una -Sbandera (suponiendo GNU tar), y vuelva a ejecutar el scp... no. Ninguna utilidad que conozco tendría una manera de saber dónde estaban los "agujeros".

tink
fuente
55
GNU cp volverá a distribuir un archivo: desde la página de manual: especifique --sparse = siempre para crear un archivo DEST disperso siempre que el archivo SOURCE contenga una secuencia suficientemente larga de cero bytes.
user25849
Increíble. Aprenda algo todos los días: ¿cuándo se introdujo esa bandera? Paga leer páginas de manual de programas "bien conocidos" de vez en cuando; D
tink
2

He tenido buena suerte con esto:

cd whatever
rsync -avxWSHAXI . .

Las -Ifuerzas de rsync para actualizar todos los archivos, independientemente de si se piensa que han cambiado o no; la -Scausa de los nuevos archivos que se sparsified. -ahace que suceda de forma recursiva para que pueda esparcir árboles de directorios completos en un solo comando.

No es tan bueno como una herramienta a medida que busca agujeros y los destruye FALLOC_FL_PUNCH_HOLE, pero es mejor que tener que duplicar árboles de directorios completos.

David dado
fuente