Kann eine Datei, die ursprünglich dünn war und dann erweitert wurde, wieder dünn gemacht werden?

29

Ich weiß, dass das Kopieren oder Übertragen einer ursprünglich spärlichen Datei ohne ein Hilfsprogramm, das spärliche Dateien versteht, dazu führt, dass die "Löcher" ausgefüllt werden. Gibt es eine Methode oder ein Hilfsprogramm, um eine ehemals dünn besetzte Datei wieder in dünn zu verwandeln?

Zum Beispiel:
Sparse-Datei erstellen:

% 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

Gibt es einen Weg zu:

% 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
quelle
Entschuldigung, ich musste die ursprünglichen Fragen ...
user25849
1
Das einzige, was ich bisher gesehen habe, ist ein GNU 'cp', wie in '% cp --sparse = immer früher-sparse-Datei neu-sparse-Datei' Der Kritiker ist, dass es nicht geht ' an Ort und Stelle'.
user25849
Wenn Sie eine Sparse-Datei kopieren möchten und die Kopie dünn sein lassen möchten, verwenden Sie rsync -aS.
Gilles 'SO- hör auf böse zu sein'

Antworten:

30

Bearbeiten Sie 2015

ab util-linux 2.25 hat das dienstprogramm unter linux fallocateeine -d/ --dig-holeoption dafür.

fallocate -d the-file

Würde für jeden Block voller Nullen in der Datei ein Loch graben


Auf älteren Systemen können Sie dies von Hand tun:

Linux hat eine FALLOC_FL_PUNCH_HOLEOption, fallocatedie dies tun kann. Ich habe ein Skript auf Github mit einem Beispiel gefunden:

Verwendung von FALLOC_FL_PUNCH_HOLE aus Python

Ich habe es ein wenig modifiziert, um das zu tun, worum Sie gebeten haben - Löcher in Bereiche von Dateien zu stanzen, die mit Nullen gefüllt sind. Hier ist es:

Verwenden von FALLOC_FL_PUNCH_HOLE aus Python, um Löcher in Dateien zu stanzen

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

Beispiel:

# 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

Beachten Sie, dass punch.pynur Blöcke mit 4096 Bytes zum Ausstanzen gefunden werden, sodass eine Datei möglicherweise nicht genau so dünn wie zu Beginn ist. Es könnte natürlich schlauer gemacht werden. Außerdem ist es nur leicht getestet , seien Sie also vorsichtig und machen Sie Backups, bevor Sie ihm vertrauen!

Jim Paris
quelle
1
Mir gefällt dies am besten, weil es nicht erforderlich ist, die gesamte Datei erneut zu schreiben.
Peter
8

Wenn Sie eine Datei sparsam machen möchten, können Sie dies direkt mit tun dd.

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

Aus dem dd(1)Handbuch:

          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.

Beachten Sie also, dass nur dann nach vorne gesucht wird, wenn der gesamte Block leer ist. Für maximale Sparsamkeit verwenden bs=1.

Bahamat
quelle
2
Jede Blockgröße, die kleiner als ist, bs=512ist nicht wirklich sinnvoll, da Festplatten Blockgeräte sind. ( bs=4096in neueren Laufwerken)
Lapo
sieht aus wie dies entsprichtcp --sparse=always zeropadded.iso isnowsparse.iso
maxschlepzig
2

Es tarfehlt ein -SFlag (unter der Annahme von GNU-Teer), und es wird erneut ausgeführt scp... nein. Kein Dienstprogramm, von dem ich weiß, hätte eine Möglichkeit zu wissen, wo die "Löcher" waren.

basteln
quelle
5
GNU cp analysiert eine Datei neu: Auf der Manpage: Geben Sie --sparse = immer an, um eine DEST-Datei mit geringer Dichte zu erstellen, wenn die SOURCE-Datei eine ausreichend lange Folge von Null-Bytes enthält.
User25849
Genial. Lerne jeden Tag etwas - wann wurde diese Flagge eingeführt? Es
lohnt sich, ab und zu
2

Ich hatte viel Glück damit:

cd whatever
rsync -avxWSHAXI . .

Das -Ierzwingt, dass rsync alle Dateien aktualisiert, unabhängig davon, ob es denkt, dass sie geändert wurden oder nicht. Das -Sbewirkt, dass die neuen Dateien sparsifiziert werden. -aDies geschieht rekursiv, sodass Sie ganze Verzeichnisbäume in einem Befehl sparsifizieren können.

Es ist nicht so gut wie ein maßgeschneidertes Tool, das Löcher ausfindig macht und sie damit zerstört FALLOC_FL_PUNCH_HOLE, aber es ist besser, als ganze Verzeichnisbäume zu duplizieren.

David Given
quelle