Um arquivo originalmente esparso e expandido pode ser esparso novamente?

28

Eu sei que copiar ou transferir o que era originalmente um arquivo esparso sem usar um utilitário que entende arquivos esparsos fará com que os 'buracos' sejam preenchidos. Existe um método ou utilitário para transformar o que antes era um arquivo esparso em esparso?

Por exemplo:
criar arquivo esparso:

% 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

Existe alguma maneira 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
    
por user25849 16.10.2012 / 19:40

4 respostas

27

Editar 2015

a partir do util-linux 2.25, o utilitário fallocate no Linux tem uma opção -d / --dig-hole para isso.

fallocate -d the-file

Cavaria um buraco para cada bloco cheio de zeros no arquivo

Em sistemas mais antigos, você pode fazer isso manualmente:

O Linux tem uma opção FALLOC_FL_PUNCH_HOLE para fallocate que pode fazer isso. Eu encontrei um script no github com um exemplo:

Usando o FALLOC_FL_PUNCH_HOLE do Python

Eu modifiquei um pouco para fazer o que você pediu - faça furos em regiões de arquivos preenchidos com zeros. Aqui está:

Usando o FALLOC_FL_PUNCH_HOLE do Python para fazer furos nos arquivos

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

Exemplo:

# 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

Observe que punch.py só encontra blocos de 4096 bytes para perfurar, portanto, pode não tornar um arquivo exatamente tão esparso quanto era quando você começou. Poderia ser mais inteligente, é claro. Além disso, é apenas ligeiramente testado , por isso tome cuidado e faça backups antes de confiar nele!

    
por 16.10.2012 / 23:10
7

Se você quiser tornar um arquivo esparso, pode fazer isso diretamente com dd .

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

Do manual dd(1) :

          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.

Portanto, observe que ele só buscará com antecedência se o bloco inteiro estiver vazio. Para máxima dispersão, use bs=1 .

    
por 17.10.2012 / 00:52
2

A abreviação de tar com um sinal -S (assumindo o tar GNU) e reexecutando o scp ... no. Nenhum utilitário que conheço teria uma maneira de saber onde estavam os "buracos".

    
por 16.10.2012 / 21:23
2

Eu tive boa sorte com isso:

cd whatever
rsync -avxWSHAXI . .

O -I força o rsync a atualizar todos os arquivos, independentemente de achar que eles mudaram ou não; o -S faz com que os novos arquivos sejam dispersos. -a faz isso acontecer de forma recursiva, para que você possa dispersar árvores de diretório inteiras em um comando.

Não é tão bom quanto uma ferramenta personalizada que procura por buracos e os destrói com FALLOC_FL_PUNCH_HOLE , mas é melhor do que ter que duplicar árvores inteiras de diretório.

    
por 19.12.2013 / 22:08