È possibile rendere nuovamente sparso un file che era originariamente sparso e quindi espanso?


29

So che copiare o trasferire ciò che originariamente era un file sparse senza usare un'utilità che capisce i file sparsi causerà la compilazione dei "buchi". Esiste un metodo o un'utilità per trasformare quello che una volta era un file sparse in sparse?

Ad esempio:
creare un file sparse:

% 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

C'è un modo per:

% 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

Mi dispiace, ho dovuto
correggere le domande

1
L'unica cosa che può fare questo da tutto quello che ho visto è un GNU 'cp', come in '% cp --sparse = sempre file precedentemente sparso file appena sparso' Il detrattore è che non lo farà ' a posto'.
user25849

Se si desidera copiare un file sparse e lasciare che la copia sia sparsa, utilizzare rsync -aS.
Gilles 'SO- smetti di essere malvagio' il

Risposte:


30

Modifica 2015

a partire da util-linux 2.25, l' fallocateutility su Linux ha un'opzione -d/ --dig-holeper quello.

fallocate -d the-file

Scaverebbe un buco per ogni blocco pieno di zeri nel file


Sui sistemi più vecchi, puoi farlo a mano:

Linux ha FALLOC_FL_PUNCH_HOLEun'opzione per fallocatefarlo. Ho trovato uno script su github con un esempio:

Utilizzo di FALLOC_FL_PUNCH_HOLE da Python

L'ho modificato un po 'per fare quello che mi hai chiesto: fai dei buchi in regioni di file piene di zeri. Ecco qui:

Utilizzo di FALLOC_FL_PUNCH_HOLE da Python per eseguire buchi nei file

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

Esempio:

# 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

Nota che punch.pytrova solo blocchi di 4096 byte da eseguire, quindi potrebbe non rendere un file esattamente sparso come lo era quando hai iniziato. Potrebbe essere reso più intelligente, ovviamente. Inoltre, è solo leggermente testato , quindi fai attenzione e fai backup prima di fidarti!


1
Mi piace di più perché non richiede di riscrivere nuovamente l'intero file.
Peter,

8

Se vuoi rendere un file sparso puoi farlo direttamente con dd.

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

Dal dd(1)manuale:

          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.

Quindi, nota che cercherà solo se l'intero blocco è vuoto. Per il massimo utilizzo di scarsità bs=1.


2
Qualsiasi dimensione di blocco inferiore a bs=512non ha davvero senso, poiché i dischi sono dispositivi a blocchi. ( bs=4096nelle unità più recenti)
lapo

sembra che questo sia equivalente acp --sparse=always zeropadded.iso isnowsparse.iso
maxschlepzig il

2

A corto di- tarup con un -Sflag (assumendo tar GNU), e rieseguendo il scp... no. Nessuna utilità di cui sono a conoscenza avrebbe modo di sapere dove fossero i "buchi".


5
GNU cp ridimensionerà un file: Dalla pagina man: Specifica --sparse = sempre per creare un file DEST sparso ogni volta che il file SOURCE contiene una sequenza abbastanza lunga di zero byte.
user25849

Eccezionale. Impara qualcosa ogni giorno: quando è stata introdotta quella bandiera? Paga di tanto in tanto leggere pagine man di programmi "ben noti"; D
tink

2

Ho avuto buona fortuna con questo:

cd whatever
rsync -avxWSHAXI . .

Le -Iforze rsync per aggiornare tutti i file, indipendentemente dal fatto che pensi di aver cambiato o no; -Scausa la sparizione dei nuovi file. -afa accadere ricorsivamente in modo da poter sparsificare interi alberi di directory in un solo comando.

Non è buono come uno strumento su misura che caccia buchi e li distrugge con FALLOC_FL_PUNCH_HOLE, ma è meglio che dover duplicare interi alberi di directory.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.