Какой лучший способ снова объединить файлы после их разделения?


73

Если у меня большой файл и мне нужно разбить его на 100 мегабайт, я сделаю

split -b 100m myImage.iso

Это обычно дает мне что-то вроде

xaa
xab
xac
xad

И чтобы вернуть их вместе, я использовал

cat x* > myImage.iso

Похоже, должен быть более эффективный способ, чем чтение каждой строки кода в группе файлов catи перенаправление вывода в новый файл. Как способ просто открыть два файла, удалить EOFмаркер из первого и соединить их - без необходимости просматривать все содержимое.

Windows / DOS имеет команду копирования для двоичных файлов. В справке упоминается, что эта команда была разработана для возможности объединения нескольких файлов. Он работает с этим синтаксисом: ( /bдля двоичного режима)

copy /b file1 + file2 + file3 outputfile

Есть ли что-то похожее или лучший способ объединения больших файлов в Linux, чем cat?

Обновить

Кажется, что catэто действительно правильный и лучший способ объединения файлов. Рад, что я все время использовал правильную команду :) Спасибо всем за ваши отзывы.


22
Примечание: лучше не использовать cat x*, потому что порядок файлов зависит от настроек вашего языка. Лучше начать печатать cat x, чем нажать Esc, а затем *- вы увидите расширенный порядок файлов и сможете изменить порядок.
rozcietrzewiacz

16
Вместо этого cat x*вы можете рассмотреть расширение оболочки скобки, cat xa{a..g}которое расширяет указанную последовательность до cat xaa xab xac xad xae xaf xag
Peter.O

3
@rozcietrzewiacz - не могли бы вы привести пример того, как я могу изменить настройку локали, которая сломается cat x*? Будет ли новая установка локали также не влияет , splitтак что если splitи cat x*были использованы в той же системе , что они всегда будут работать?
cwd

3
«открытие двух файлов, удаление маркера EOF из первого и подключение их - без необходимости просматривать все содержимое.» ... звучит так, как будто вам нужно изобрести новую файловую систему, чтобы делать то, что вы хотите
JoelFan

6
@cwd: Глядя split.cв GNU Coreutils, суффиксы построены из фиксированного массива символов: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. Суффикс не будет зависеть от локали. (Но я не думаю, что какой-либо здравомыслящий язык переставил бы строчные буквы; даже EBCDIC поддерживает их стандартный порядок.)
Кит Томпсон,

Ответы:


50

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


cat x, then press EscТрюк вы упомянули аккуратный .. Я искал что - то подобное, спасибо ... хороший комментарий и хороший ответ
Peter.O

2
Добро пожаловать :) Кроме того, когда у вас есть этот список файлов в командной строке, вы можете использовать, Ctrl+Wчтобы вырезать слово, а затем Ctrl+Yвставить его.
rozcietrzewiacz

кошка означает "
сцепить

4
... и "cateate" происходит от латинского слова "catena", что означает "цепь" ... сцепление - это соединение звеньев цепи. ... (и немного дальше от темы, кривая контактной цепочки также выводится из "catena". Так цепочка висит)
Peter.O

19

Под капотом

Нет более эффективного способа, чем копирование первого файла, затем копирование второго файла после него и так далее. Обе DOS copyи так и catделают.

Каждый файл хранится независимо от других файлов на диске. Почти каждая файловая система, предназначенная для хранения данных на дисковом устройстве, работает блоками. Вот очень упрощенное представление о том, что происходит: диск разделен на блоки, скажем, 1 КБ, и для каждого файла операционная система хранит список блоков, из которых он состоит. Большинство файлов не имеют целое число длинных блоков, поэтому последний блок занят только частично. На практике файловые системы имеют много оптимизаций, таких как совместное использование последнего частичного блока между несколькими файлами или сохранение «блоков с 46798 по 47913» вместо «блока 46798, блока 46799,…». Когда операционной системе необходимо создать новый файл, она ищет свободные блоки. Блоки не должны быть последовательными: если только блоки 4, 5, 98 и 178 свободны, вы все равно можете сохранить файл 4 КБ.

Вы могли бы поддерживать частичные блоки в середине файла, но это добавило бы значительную сложность, особенно при доступе к файлам не последовательно: чтобы перейти к 10340-му байту, вы больше не могли перейти к 100-му байту 11-го блока. проверить длину каждого промежуточного блока.

Учитывая использование блоков, вы не можете просто соединить два файла, потому что обычно первый файл заканчивается в середине блока. Конечно, у вас может быть особый случай, но только если вы хотите удалить оба файла при объединении. Это будет очень специфическая обработка для редкой операции. Такая специальная обработка не существует сама по себе, потому что в типичной файловой системе доступ ко многим файлам осуществляется одновременно. Поэтому, если вы хотите добавить оптимизацию, вам нужно тщательно подумать: что произойдет, если какой-то другой процесс читает один из задействованных файлов? Что произойдет, если кто-то попытается объединить А и В, а кто-то соединит А и С? И так далее. В целом, эта редкая оптимизация была бы огромным бременем.

В общем, вы не можете сделать объединение файлов более эффективным, не делая больших жертв в другом месте. Это того не стоит.

На расщепление и присоединение

splitи catпростые способы разделения и объединения файлов. splitзаботится о создании файлов с именами в алфавитном порядке, так что cat *работает для объединения.

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

Существуют утилиты сжатия, которые создают многочастные архивы, такие как zipsplitи rar -v. Они не очень удобны, потому что они сжимают и упаковывают (собирают несколько файлов в один) в дополнение к разбиению (и наоборот распаковывают и распаковывают в дополнение к объединению). Но они полезны тем, что они проверяют, что у вас есть все части, и что части завершены.


8

Похоже, должен быть более эффективный способ, чем передача всего содержимого через stdin/stdout

За исключением того, что на самом деле не то, что происходит. Оболочка подключает стандартный вывод cat напрямую к открытому файлу, что означает, что «проход через стандартный вывод» аналогичен записи на диск.


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

@cwd Можно было бы спроектировать файловую систему, в которой вы могли бы таким образом объединить два файла, но это очень усложнило бы дизайн файловой системы. Вы бы оптимизировали эту операцию за счет усложнения и замедления многих общих задач.
Жиль "ТАК - перестань быть злым"

@ Жиль - было бы интересно узнать больше о деталях низкого уровня. Для меня чтение всех секторов с жесткого диска для нескольких файлов и последующий сброс их в другие неиспользуемые сектора на диске кажется неэффективным. И я думаю, что большие файлы должны иногда храниться в нескольких блоках свободных секторов, потому что не всегда может быть достаточно блоков рядом для их хранения. Поэтому теоретически вы можете объединить файлы в один, убрав маркер EOF и указав на группу секторов в начале следующего файла. * nix мощный, поэтому я подумал, что есть лучший способ, чем cat.
cwd

@cwd Там нет «маркер EOF». Ни одна здравомыслящая современная файловая система не работает так, потому что она предотвращает появление некоторых символов в файлах (или требует сложных кодировок). Но даже если бы был маркер EOF, большую часть времени у вас не было бы нужного файла после него.
Жиль "ТАК - перестань быть злым"

Я имел в виду концепцию маркера EOF, а не фактический маркер EOF. Иначе, если вы посмотрите на биты и байты файла на жестком диске, как вы узнаете, где он заканчивается? Вы указываете длину файла в начале? Я говорю о действительно низком уровне. Это то, что вы также имеете в виду?
cwd

3

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

Итак, я написал кучу программ:

  • один, чтобы «высосать» файл, прочитав его, отправив в stdout и, если закончите, удалите его
  • и один для буферизации данных «на лету».

Это позволило мне сделать что-то вроде

partto sourcefile | mybuffer 128M >>cumufile

и, таким образом, удаляя исходный файл, пока 128M был еще не записан. Немного опасно, но если данные не так уж ценны или они существуют где-то еще, это выполнимо.

При необходимости могу предоставить источник.


0

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

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

А потом использовать myImage.iso, например

$ md5sum myImage.iso

Хотя, конечно myImage.iso, это специальный файл (именованный канал), а не обычный файл, так что это может быть полезно или нет в зависимости от того, что вы пытаетесь сделать.


0

Разделение файлов

Разделить по размеру

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

split -b 500M videos\BigVideoFile.avi SmallFile.

Таким образом, вы решили разделить один большой файл на более мелкие части по 500 МБ. Также вы хотите, чтобы имена файлов деталей были SmallFile. Обратите внимание, что вам нужно точка после имени файла. Результатом должно стать создание новых файлов, таких как:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Разделить по количеству линий

Таким образом, вы разбиваете текстовый файл на файлы меньшего размера, ограниченные 50 строками.

split -l 50 text_to_split.txt

Результат должен быть примерно таким:

xaa xab xac ...

Разделить байтами

Разделить на небольшие файлы с произвольным размером небольших файлов в байтах:

split -b 2048 BigFile.mp4

Результат должен быть аналогичен результату разделения по количеству строк .

Присоединение файлов

Вы можете объединить файлы двумя способами. Первый из них:

cat SmallFile.* > OutputBigVideoFile.avi

или с:

cat SmallFile.?? > OutputBigVideoFile.avi

Примечание. При объединении файлов небольшие файлы не должны быть повреждены. Также все маленькие (частично) файлы должны находиться в одном каталоге.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.