Um arquivo originalmente esparso e depois expandido pode ser esparso novamente?

29

Sei que copiar ou transferir o que era originalmente um arquivo esparso sem usar um utilitário que entenda arquivos esparsos fará com que os 'furos' sejam preenchidos. Existe um método ou utilitário para ativar o que antes era um arquivo esparso?

Por exemplo:
crie um 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
user25849
fonte
Desculpe, eu tive que muito se as ques originais ...
user25849
1
A única coisa que pode fazer isso de tudo que eu vi é um GNU 'cp', como em '% cp --sparse = sempre arquivo anteriormente esparso arquivo recém-esparso' O detrator é que não fará isso ' no lugar'.
user25849
Se você deseja copiar um arquivo esparso e permitir que a cópia seja esparsa, use rsync -aS.
Gilles 'SO- stop be evil'

Respostas:

30

Edit 2015

a partir do util-linux 2.25, o fallocateutilitário no Linux tem uma opção -d/ --dig-holepara 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 FALLOC_FL_PUNCH_HOLEopção para fallocateisso. Encontrei um script no github com um exemplo:

Usando FALLOC_FL_PUNCH_HOLE do Python

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

Usando FALLOC_FL_PUNCH_HOLE do Python para fazer furos em 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.pyapenas blocos de 4096 bytes são perfurados, portanto, ele pode não tornar um arquivo exatamente tão esparso quanto era quando você iniciou. Poderia ser mais inteligente, é claro. Além disso, ele é apenas levemente testado ; portanto, tenha cuidado e faça backups antes de confiar nele!

Jim Paris
fonte
1
Eu gosto disso da melhor maneira, porque não exige a reescrita de todo o arquivo.
Peter Peter
8

Se você deseja tornar um arquivo escasso, pode fazê-lo diretamente com dd.

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

Do 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.

Portanto, observe que ele buscará apenas se o bloco inteiro estiver vazio. Para uso escasso máximo bs=1.

bahamat
fonte
2
Qualquer tamanho de bloco menor do bs=512que realmente não faz sentido, pois os discos são dispositivos de bloco. ( bs=4096em unidades mais recentes)
lapo 22/01
parece que isso é equivalente acp --sparse=always zeropadded.iso isnowsparse.iso
maxschlepzig 26/11
2

Curto tar-lo com uma -Sbandeira (assumindo tar GNU), e re-executando o scp... não. Nenhum utilitário que eu conheça teria como saber onde estavam os "buracos".

consertar
fonte
5
O GNU cp irá analisar novamente um arquivo: Na página de manual: Especifique --sparse = sempre para criar um arquivo DEST esparso sempre que o arquivo SOURCE contiver uma sequência suficientemente longa de zero bytes.
user25849
Impressionante. Aprenda algo todos os dias - quando essa bandeira foi introduzida? Vale a pena ler páginas de manual de programas "conhecidos" de vez em quando; D
tink
2

Eu tive boa sorte com isso:

cd whatever
rsync -avxWSHAXI . .

As -Iforças rsync para atualizar todos os arquivos, independentemente de ele pensa que eles mudaram ou não; isso -Sfaz com que os novos arquivos sejam esparsos. -afaz com que isso aconteça recursivamente para que você possa sparsify árvores de diretório inteiras em um comando.

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

David Given
fonte