Быстрое объединение нескольких файлов в Linux

Я использую многопроцессорную обработку Python для создания временного выходного файла для каждого процесса. Они могут быть размером несколько GBs, и я делаю несколько десятков из них. Эти временные файлы должны быть объединены, чтобы сформировать желаемый результат, и это шаг, который оказывается узким местом (и убийцей параллелизма). Есть ли инструмент Linux, который создаст конкатированный файл, изменив метаданные файловой системы и фактически не скопировав содержимое ? Пока он работает на любой системе Linux, которая будьте приемлемы для меня. Но решение для файловой системы не будет иметь большой помощи.

Я не обучен OS или CS, но теоретически кажется, что можно создать новый индекс и скопировать структуру указателя индекса из индекса файлов, из которых я хочу скопировать, а затем разорвать эти индексы. Есть ли какая-то польза, которая сделает это ? Учитывая избыток хорошо продуманных утилит unix, я полностью ожидал, что это будет, но ничего не смог найти. Отсюда мой вопрос о SO. Папка система находится на блочном устройстве, на жестком диске, Если эта информация имеет значение. У меня нет уверенности, чтобы написать это самостоятельно, так как я никогда не занимался программированием на системном уровне, поэтому любые указатели (на фрагменты кода C/Python) будут очень полезны.

6 ответов


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

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

  1. перед началом многопроцессорной обработки создайте конечный выходной файл и увеличьте ее окончательный размер от fseek()ing в конце концов, это создаст разреженным файлом.

  2. начните мультипроцессинг, вручая каждому процессу ФД и смещение в свое конкретный фрагмент файла.

таким образом, процессы будут совместно заполняют один выходной файл, избавляясь от необходимости сводить их вместе позже.

редактировать

если вы не можете предсказать размер индивидуальные файлы, но потребитель окончательный файл может работать с последовательным (в отличие от случайного доступа) входом, вы можете кормить cat tmpfile1 .. tmpfileN потребителю, либо на stdin

cat tmpfile1 ... tmpfileN | consumer

или через именованные каналы (используя замену процесса bash):

consumer <(cat tmpfile1 ... tmpfileN)

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

в этом решении ваши производящие и потребляющие приложения остаются неизменными. Производители выписывают кучу файлов, которые делает слой предохранителей появляется отдельным файлом. Этот затем виртуальный файл представляется потребителю.

FUSE имеет привязки для множества языков,включая Python. Если вы посмотрите на некоторые примеры здесь или здесь (это для разных Привязок), для этого требуется удивительно мало кода.


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

вместо объединения этих файлов я хотел бы предложить перепроектировать инструмент анализа для поддержки поиска из нескольких файлов. Например, многие анализаторы журналов поддерживают чтение файлов журналов в течение одного дня.

редактировать

@san: как вы говорите код в использование вы не можете контролировать, ну вы можете объединить отдельные файлы на лету, используя именованные каналы:

$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat

для 4 файлов; ХАА, xab, xac ПО, на амберлите xAD быстрый concatention в bash (как root):

losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad

(предположим, что loop0, loop1, loop2, loop3-это имена новых файлов устройств.)

поставить http://pastebin.com/PtEDQH7G в файл сценария "join_us". Тогда вы можете использовать его следующим образом:

./join_us /dev/loop{0..3}

затем (если этот большой файл является фильмом) вы можете дать его право собственности обычному пользователю (chown itsme / dev / mapper / joined), а затем он / она может воспроизвести его через: mplayer/dev/mapper / присоединился

очистка после них (как root):

dmsetup remove joined; losetup -d /dev/loop[0123]

нет, нет такого инструмента или операции.

вы можете исследовать, возможно ли для каждого процесса записывать непосредственно в окончательный файл. Скажем, процесс 1 записывает байты 0-X, процесс 2 записывает X-2X и так далее.


потенциальной альтернативой является cat все ваши временные файлы в именованный канал, а затем использовать этот именованный канал в качестве входных данных для вашей программы с одним входом. Пока ваша программа с одним входом просто читает вход последовательно и не ищет.