Який найкращий спосіб знову приєднати файли після їх розбиття?


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

кішка означає "конкатенат"
JoelFan

4
.. і «зчіплювати» derrives від латинського слова «Катена» , що означає «ланцюг» .. конкатенація приєднується вгору ланки ланцюга. ... (і трохи далі поза темою, крива каналів також походить від "катени". Це так, як висить ланцюг)
Peter.O

19

Під капотом

Не існує більш ефективного способу, ніж скопіювати перший файл, потім скопіювати другий файл після нього тощо. І DOS, copyі catце роблять.

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

Ви могли б підтримувати часткові блоки в середині файлу, але це додало б значної складності, особливо при доступі до файлів не послідовно: щоб перейти до 10340-го байти, ви більше не могли перейти до 100-го байту 11-го блоку, перевірити довжину кожного втручається блоку.

Зважаючи на використання блоків, ви не можете просто приєднати два файли, оскільки загалом перший файл закінчується в середині блоку. Звичайно, у вас може бути особливий випадок, але лише якщо ви хочете видалити обидва файли при об'єднанні. Це було б дуже специфічним поводженням для рідкісної операції. Така спеціальна обробка не працює сама по собі, оскільки в типовій файловій системі багато файлів одночасно доступні. Отже, якщо ви хочете додати оптимізацію, вам потрібно добре подумати: що станеться, якщо якийсь інший процес читає один із залучених файлів? Що станеться, якщо хтось намагається об'єднати A і B, тоді як хтось об'єднує A і C? І так далі. Загалом ця рідкісна оптимізація була б величезним тягарем.

Загалом, ви не можете зробити об'єднання файлів більш ефективним, не роблячи великих жертв в іншому місці. Це не варто.

Про розщеплення та приєднання

splitі catце прості способи розділення та з'єднання файлів. splitдбає про створення файлів, названих в алфавітному порядку, щоб вони cat *працювали для приєднання.

Мінусом catдля приєднання є те, що воно не є надійним щодо поширених режимів відмов. Якщо один із файлів врізаний або відсутній, catне буде скаржитися, ви просто отримаєте пошкоджений вихід.

Існують утиліти стиснення, які виробляють багаточастинні архіви, такі як zipsplitі rar -v. Вони не дуже одноманітні, тому що вони стискають і пакують (збирають кілька файлів в один) на додаток до розбиття (і навпаки, розпаковують і розпаковують на додаток до об'єднання). Але вони корисні тим, що вони підтверджують, що у вас є всі деталі, і що деталі є комплектними.


8

Здається, що існує більш ефективний спосіб, ніж передача всього вмісту через систему stdin/stdout

За винятком того, що насправді не відбувається. Оболонка з'єднує stdout cat безпосередньо до відкритого файлу, а це означає, що "пройти stdout" - це те саме, що записувати на диск.


Я просто уявляв, як за допомогою кота відобразити декілька гігабайт коду в консолі, потім він захопив і поставив у файл. Це ментальний образ, який я маю на те, що повинно відбуватися, коли я використовую cat і перенаправляю висновок, який я не бачу. Просто здавалося, що якби ви могли відкрити два файли, з'єднати їх, а потім закрити їх було б ефективніше, ніж пробігнути всі рядки коду cat. Дякуємо, що повідомили мені про прямий зв’язок.
cwd

@cwd Можна було б сконструювати файлову систему, де ви могли би таким чином з'єднати два файли, але це дуже ускладнить дизайн файлової системи. Ви б оптимізували для однієї операції ціною, щоб зробити багато загальних завдань складнішими та повільнішими.
Жиль

@Gilles - було б цікаво дізнатися більше про деталі низького рівня. Мені читання всіх секторів з жорсткого диска для декількох файлів, а потім скидання їх назад в інші невикористані сектори на диску здається неефективним. І я думаю, що великі файли потрібно зберігати в декількох блоках вільних секторів часом, тому що не завжди може бути достатньо блоків поруч, щоб зберігати їх. Тому теоретично ви можете об'єднати файли в один, видаливши маркер EOF і вказуючи на групу секторів на початку наступного файлу. * nix потужний, тому я поцікавився, чи немає кращого способу, ніж кіт.
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.