У меня есть почтовый файл на 50 ГБ, который содержит примерно 50 000 изображений JPG. Разархивированные файлы размером около 55 ГБ. Я на Ubuntu 16.04.

Но у меня в этой системе только 70 ГБ. Таким образом, я получаю ошибку диска в середине распаковки.

Могу ли я разархивировать файл и в то же время уменьшить размер файла ZIP (например, удалить данные из разархивированных jpgs), чтобы все уместилось на моем диске?

--- Тот же вопрос для Windows существует ---

У кого-то был такой же вопрос для Windows: разархивировать файл на маленький диск

Предложенные решения, к сожалению, не решают проблему для меня в Linux (и, похоже, ни одна из них не решает проблему хорошо в Windows). Так что я держу этот вопрос на случай, если есть хорошее решение для Linux. Спасибо за комментарии.

2 ответа2

0

Вы можете попробовать воспользоваться системным вызовом, специфичным для Linux, fallocate или эквивалентом командной строки. Режим FALLOC_FL_PUNCH_HOLE позволяет обнулить любую заданную часть файла, и, где возможно, затронутые блоки возвращаются обратно в файловую систему, создавая разреженный файл.

Не все файловые системы поддерживают этот вызов, но ext4 поддерживает.

Идея состоит в том, что вы извлекаете файл из архива, а затем используете fallocate, чтобы обнулить часть архива, которую он занимал. Словарь zip-архива содержит смещение к началу заголовка каждого файла и сжатую длину файла в архиве.

В качестве примера концепции приведен минимальный скрипт Python3 для извлечения и выполнения системного вызова для каждого файла. Вы не должны использовать его без тщательного тестирования. Вы можете сделать то же самое в сценарии оболочки, если сможете извлечь информацию. Для меня fallocate не входил в стандартную библиотеку Python, поэтому в первой половине скрипта для ее вызова используется ctypes. Сценарию нужна библиотека Python Zipfile. Также могут потребоваться другие изменения для вашей системы. Сумма обнуления не включает размер заголовка, который не дает им стать одной смежной областью.

#!/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)

Я проверил его на простом zip-архиве, и вы можете увидеть в первом столбце количество блоков, используемых архивом, уменьшающихся при извлечении каждого файла:

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
0

Вы можете использовать встроенный в GNOME Archive Manager чтобы открыть zip-файл без распаковки. Открыв его, вы можете скопировать ~ 10-15 ГБ файлов в папку, в которую вы хотите их извлечь, а затем удалить их из архива. Промыть и повторить.

Есть несколько утилит, которые имеют эту функцию (Archive- Mounter, archivemount, GVFS, AVFS), но Archive Manager имеет очень удобный графический интерфейс и, вероятно, будет самым простым в использовании.

Кроме того, вы можете подключить внешний диск и использовать его в качестве временного хранилища.

Примечание: в Windows есть возможность монтировать zip-файлы, как это встроено, я удивлен, что никто не указал на это в другой теме.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .