Sie können versuchen, die Linux-spezifischen Fallocate-Systemaufrufe oder das Befehlszeilenäquivalent zu nutzen. In diesem FALLOC_FL_PUNCH_HOLE
Modus können Sie einen beliebigen Teil einer Datei auf Null setzen und die betroffenen Blöcke werden, sofern möglich, wieder an das Dateisystem freigegeben, wodurch eine spärliche Datei entsteht.
Nicht alle Dateisysteme unterstützen diesen Aufruf, Ext4 jedoch.
Die Idee ist, dass Sie eine Datei aus dem Archiv extrahieren und dann mit fallocate den von ihr belegten Teil des Archivs auf Null setzen. Das Wörterbuch des ZIP-Archivs enthält den Versatz zum Anfang des Kopfs jeder Datei und die komprimierte Länge der Datei innerhalb des Archivs.
Als Beispiel für das Konzept ist hier ein minimales Python3-Skript zum Extrahieren und Ausführen des Systemaufrufs für jede Datei. Sie sollten es nicht ohne sorgfältige Tests verwenden. Möglicherweise können Sie dasselbe in einem Shellskript tun, wenn Sie die Informationen extrahieren können. fallocate war für mich nicht in einer Standard-Python-Bibliothek, daher wird sie in der ersten Hälfte des Skripts mit ctypes aufgerufen. Das Skript benötigt die Python-Zipfile-Bibliothek. Es können auch andere Änderungen für Ihr System erforderlich sein. Die Höhe des Nullpunkts enthält nicht die Größe der Kopfzeile, sodass sie nicht zu einem zusammenhängenden Bereich werden.
#!/usr/bin/python3 # https://superuser.com/a/1371106/458747 # int fallocate(int fd, int mode, off_t offset, off_t len) import ctypes libc = ctypes.cdll.LoadLibrary("libc.so.6") fallocate = libc.fallocate fallocate.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_longlong, ctypes.c_longlong) FALLOC_FL_PUNCH_HOLE = 2 FALLOC_FL_KEEP_SIZE = 1 import sys, subprocess, zipfile # will need zlib for compression myzip = sys.argv[1] fd = open(myzip,"r+") fno = fd.fileno() zf = zipfile.ZipFile(myzip, 'r') for info in zf.infolist(): zf.extract(info) # print(info.header_offset,info.compress_size) rc = fallocate(fno, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, info.header_offset, info.compress_size) if rc!=0: print("fallocate failed\n") subprocess.call("ls -ls "+myzip,shell=True)
Ich habe es in einem einfachen Zip-Archiv getestet. In der ersten Spalte sehen Sie die Anzahl der Blöcke, die vom Archiv verwendet werden.
24224 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 23292 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 22524 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 21524 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip ... 2800 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 1868 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 880 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip 124 -rw-r--r-- 25562742 Oct 29 22:56 ../my.zip