Un fichier initialement clairsemé puis développé peut-il être à nouveau clairsemé?

29

Je sais que la copie ou le transfert de ce qui était à l'origine un fichier clairsemé sans utiliser un utilitaire qui comprend les fichiers clairsemés entraînera le remplissage des «trous». Existe-t-il une méthode ou un utilitaire pour transformer ce qui était autrefois un fichier clairsemé en clairsemé?

Par exemple:
créez un fichier clairsemé:

% 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-t-il un moyen 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
la source
Désolé, j'ai dû
refaire les
1
La seule chose qui puisse faire cela de tout ce que j'ai vu est un GNU 'cp', comme dans '% cp --sparse = toujours anciennement-fichier-rare nouveau-fichier-éparse' Le détracteur est qu'il ne le fera pas ' en place'.
user25849
Si vous souhaitez copier un fichier clairsemé et laisser la copie clairsemée, utilisez rsync -aS.
Gilles 'SO- arrête d'être méchant'

Réponses:

30

Edit 2015

depuis util-linux 2.25, l' fallocateutilitaire sous Linux a une option -d/ --dig-holepour cela.

fallocate -d the-file

Creuserait un trou pour chaque bloc plein de zéros dans le fichier


Sur les anciens systèmes, vous pouvez le faire à la main:

Linux a une FALLOC_FL_PUNCH_HOLEoption pour fallocatecela. J'ai trouvé un script sur github avec un exemple:

Utilisation de FALLOC_FL_PUNCH_HOLE depuis Python

Je l'ai un peu modifié pour faire ce que vous avez demandé - percer des trous dans des régions de fichiers remplis de zéros. C'est ici:

Utilisation de FALLOC_FL_PUNCH_HOLE à partir de Python pour percer des trous dans les fichiers

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

Exemple:

# 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

Notez que punch.pyne trouve que des blocs de 4096 octets à perforer, donc il se peut que le fichier ne soit pas aussi clairsemé qu'au début. Cela pourrait être rendu plus intelligent, bien sûr. De plus, il n'est que légèrement testé , alors faites attention et faites des sauvegardes avant de lui faire confiance!

Jim Paris
la source
1
J'aime le mieux car cela ne nécessite pas de réécrire le fichier entier à nouveau.
Peter
8

Si vous voulez rendre un fichier clairsemé, vous pouvez le faire directement avec dd.

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

Du dd(1)manuel:

          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.

Donc, notez qu'il ne cherchera à l'avance que si le bloc entier est vide. Pour un maximum d'économie bs=1.

bahamat
la source
2
Toute taille de bloc inférieure à bs=512n'a pas vraiment de sens, car les disques sont des périphériques de bloc. ( bs=4096dans les disques plus récents)
lapo
ressemble à cecicp --sparse=always zeropadded.iso isnowsparse.iso
maxschlepzig
2

À moins de tarle mettre en place avec un -Sdrapeau (en supposant GNU tar), et de ré-exécuter le scp... non. Aucun utilitaire que je connais n'aurait un moyen de savoir où étaient les "trous".

tink
la source
5
GNU cp récupérera un fichier: À partir de la page de manuel: Spécifiez --sparse = toujours pour créer un fichier DEST clairsemé chaque fois que le fichier SOURCE contient une séquence suffisamment longue de zéro octet.
user25849
Impressionnant. Apprenez quelque chose tous les jours - quand ce drapeau a-t-il été introduit? Paye pour lire des pages de manuel de programmes "bien connus" de temps en temps; D
tink
2

J'ai eu de la chance avec ça:

cd whatever
rsync -avxWSHAXI . .

Les -Iforces rsync de mettre à jour tous les fichiers, peu importe si elle pense qu'ils ont changé ou non; le -Sprovoque la raréfaction des nouveaux fichiers.-arend cela récursif afin que vous puissiez réduire les arborescences de répertoires entiers en une seule commande.

Ce n'est pas aussi bon qu'un outil sur mesure qui chasse les trous et les détruit FALLOC_FL_PUNCH_HOLE, mais c'est mieux que d'avoir à dupliquer des arborescences de répertoires entières.

David Given
la source