Недостаточно места на диске для распаковки 50 ГБ файла в Ubuntu 16.04: можно ли извлечь и уменьшить размер файла zip одновременно?

672
tyrex

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

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

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

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

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

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

0
@ Скотт Спасибо за ссылку. Мой вопрос точно такой же, за исключением того, что я смотрю на Ubuntu вместо Windows. Ответы там не работают для меня (и также не решают проблему для Windows). Должен ли я закрыть эту ветку и задать там дополнительный вопрос? Или оставьте это, поскольку могут быть конкретные решения для Ubuntu, которые работают? Спасибо за ответ. tyrex 5 лет назад 0
Оставьте это, если кто-то не найдет дубликат с решением Linux. Пока держите вопрос. «Дополнительный вопрос там» не соответствует нашей модели вопросов и ответов; Вы не должны задавать подобные вопросы ни в комментариях, ни в «ответах». Kamil Maciorowski 5 лет назад 1
Просто оставь это. Возможно [отредактируйте] это, чтобы сказать, что вы смотрели на другой вопрос и что он вам не помогает. Извините за пометку вашего вопроса как дупла, не читая его внимательно. Scott 5 лет назад 1

2 ответа на вопрос

0
meuh

Вы можете попробовать воспользоваться системным вызовом, специфичным для 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
Layne Bernardo

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

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

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

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