Intereting Posts
Как написать эту замену с условием Получение Dropbox для синхронизации по SSH Добавлен пользователь с adduser, но не может войти с этим пользователем через FTP Какую рабочую среду у меня есть? Как я могу кэшировать разблокировку PGP для перехода unix, когда я нахожусь в виртуальном терминале? Как найти альтернативные суперблоки в файловой системе ext3 без qcow2? Проверьте, существуют ли файлы в списке файлов в определенном каталоге Правила UFW, позволяющие выполнять определенное поведение Linux Mint 18 – Корица продолжает падать Предопределенный источник ввода для каждого окна в Gnome Перенаправить вывод фонового процесса на пейджер «меньше» после завершения работы не до терминала по умолчанию Две точные копии папки с использованием только FTP и командной строки Автоматически переименовывать файл, если есть дублирующееся имя файла Ctrl + D для вывода конечной линии Как найти / grep, что находится между строкой1 и строкой2?

Добавление огромных файлов друг к другу без их копирования

Существует 5 огромных файлов (file1, file2, .. file5) около 10G каждый и крайне мало свободного места на диске, и мне нужно объединить все эти файлы в один. Нет необходимости хранить оригинальные файлы, только окончательные.

Обычная конкатенация идет с cat в последовательности для файлов file2 .. file5 :

 cat file2 >> file1 ; rm file2 

К сожалению, для этого пути требуется не менее 10 Гб свободного места, которого у меня нет. Есть ли способ конкатенации файлов без фактического копирования, но как-то сказать файловой системе, что файл1 не заканчивается в исходном конце file1 и продолжается при запуске file2?

пс. файловая система ext4, если это имеет значение.

AFAIK это (к сожалению) невозможно обрезать файл с самого начала (это может быть справедливо для стандартных инструментов, но для уровня syscall см. Здесь ). Но с некоторой сложностью вы можете использовать обычное усечение (вместе с разреженными файлами): вы можете записать в конец целевого файла, не записав все данные между ними.

Предположим сначала, что оба файла имеют точно 5GiB (5120 MiB) и что вы хотите переместить 100 MiB за раз. Вы выполняете цикл, который состоит из

  1. копирование одного блока с конца исходного файла в конец целевого файла (увеличение потребляемого дискового пространства)
  2. усечение исходного файла одним блоком (освобождение дискового пространства)

     for((i=5119;i>=0;i--)); do dd if=sourcefile of=targetfile bs=1M skip="$i" seek="$i" count=1 dd if=/dev/zero of=sourcefile bs=1M count=0 seek="$i" done 

Но сначала попробуйте с меньшими тестовыми файлами, пожалуйста …

Вероятно, файлы не имеют одинакового размера и не имеют кратного размера блока. В этом случае расчет смещений становится более сложным. seek_bytes и skip_bytes .

Если это так, как вы хотите, но вам нужна помощь для деталей, тогда спросите еще раз.

Предупреждение

В зависимости dd размера блока dd результирующий файл будет фрагментарным кошмаром.

Вместо того, чтобы связывать файлы вместе в один файл, возможно, имитировать один файл с именованным каналом, если ваша программа не может обрабатывать несколько файлов.

 mkfifo /tmp/file cat file* >/tmp/file & blahblah /tmp/file rm /tmp/file 

Как предполагает Хауке, losetup / dmsetup также может работать. Быстрый эксперимент; Я создал файл 'file1..file4' и с небольшим усилием сделал:

 for i in file*;do losetup -f ~/$i;done numchunks=3 for i in `seq 0 $numchunks`; do sizeinsectors=$((`ls -l file$i | awk '{print $5}'`/512)) startsector=$(($i*$sizeinsectors)) echo "$startsector $sizeinsectors linear /dev/loop$i 0" done | dmsetup create joined 

Затем / dev / dm-0 содержит виртуальное блочное устройство с вашим файлом в качестве содержимого.

Я не проверил это хорошо.

Другое редактирование: размер файла должен быть делимым равномерно на 512 или вы потеряете некоторые данные. Если это так, тогда ты хороший. Я вижу, он также отметил это ниже.

Вам нужно будет написать что-то, что копирует данные в пучки, которые не превышают столько свободного места, которое у вас есть. Он должен работать следующим образом:

  • Прочтите блок данных из pread() (используя pread() , ища перед чтением в pread() место).
  • Добавьте блок в file1 .
  • Используйте fcntl(F_FREESP) чтобы освободить место из file2 .
  • Повторение

Я знаю, что это скорее обходное решение, чем то, о чем вы просили, но он позаботится о вашей проблеме (и с небольшой фрагментацией или headscratch):

 #step 1 mount /path/to/... /the/new/fs #mount a new filesystem (from NFS? or an external usb disk?) 

а потом

 #step 2: cat file* > /the/new/fs/fullfile 

или, если вы считаете, что сжатие поможет:

 #step 2 (alternate): cat file* | gzip -c - > /the/new/fs/fullfile.gz 

Затем (и ТОЛЬКО тогда), наконец

 #step 3: rm file* mv /the/new/fs/fullfile . #of fullfile.gz if you compressed it