Есть 5 огромных файлов (file1, file2, .. file5) по 10G каждый и на диске осталось очень мало свободного места, и мне нужно объединить все эти файлы в один. Сохранять оригинальные файлы не нужно, только конечный.
Обычная конкатенация происходит cat
последовательно для файлов file2
.. file5
:
cat file2 >> file1 ; rm file2
К сожалению, этот способ требует как минимум 10G свободного места, которого у меня нет. Есть ли способ объединить файлы без фактического копирования, но как-то сказать файловой системе, что file1 не заканчивается в конце file1 и продолжается в начале file2?
пс. файловая система ext4, если это имеет значение.
filesystems
files
порыв
источник
источник
nbd-server
.Ответы:
AFAIK (к сожалению) невозможно обрезать файл с самого начала (это может быть верно для стандартных инструментов, но для уровня системного вызова см. Здесь ). Но с добавлением некоторой сложности вы можете использовать обычное усечение (вместе с разреженными файлами): вы можете записать в конец целевого файла, не записав все данные между ними.
Предположим сначала, что оба файла имеют размер 5 ГБ (5120 МБ) и что вы хотите переместить 100 МБ за раз. Вы выполняете цикл, который состоит из
усечение исходного файла на один блок (освобождение дискового пространства)
Но сначала попробуйте меньшие тестовые файлы, пожалуйста ...
Вероятно, файлы не одинакового размера и не кратны размеру блока. В этом случае расчет смещений становится более сложным.
seek_bytes
иskip_bytes
должен быть использован тогда.Если вы хотите идти по этому пути, но вам нужна помощь для уточнения деталей, спросите еще раз.
Предупреждение
В зависимости от
dd
размера блока результирующий файл будет кошмаром фрагментации.источник
Вместо того, чтобы объединять файлы в один файл, возможно, имитируйте один файл с именованным каналом, если ваша программа не может обрабатывать несколько файлов.
Как предполагает Хауке, losttup / dmsetup также может работать. Быстрый эксперимент; Я создал 'file1..file4' и, приложив немного усилий, сделал:
Затем / dev / dm-0 содержит виртуальное блочное устройство с вашим файлом в качестве содержимого.
Я не проверял это хорошо.
Другое редактирование: размер файла должен делиться равномерно на 512, иначе вы потеряете некоторые данные. Если это так, то ты в порядке. Я вижу, он также отметил это ниже.
источник
dmsetup
виртуальное блочное устройство (которое позволяет выполнять обычные операции поиска, но не добавляет и не усекает). Если размер первого файла не кратен 512, то вы должны скопировать неполный последний сектор и первые байты из второго файла (в сумме 512) в третий файл. Устройство цикла для второго файла потребуется--offset
тогда.Вам нужно будет написать что-то, что копирует данные в пакеты, которые не превышают объем свободного места, который у вас есть. Это должно работать так:
file2
(используяpread()
поиск до чтения в правильном месте).file1
.fcntl(F_FREESP)
чтобы освободить место отfile2
.источник
fcntl(F_FREESP)
чего освобождает пространство, связанное с заданным диапазоном байтов файла (это делает его разреженным).fcntl
справочной странице (2012-04-15).fallocate
системного вызова FALLOC_FL_PUNCH_HOLE. Более новые версии утилиты fallocate отutil-linux
имеют интерфейс к этому.Я знаю, что это скорее обходной путь, чем то, что вы просили, но он позаботится о вашей проблеме (и с небольшой фрагментацией или потертостью):
а потом
или, если вы думаете, что сжатие поможет:
Тогда (и ТОЛЬКО тогда), наконец,
источник