Найшвидший спосіб об'єднання файлів


25

У мене є 10 к + файлів на загальну суму понад 20 ГБ, які мені потрібно об'єднати в один файл.

Чи є швидший шлях, ніж

cat input_file* >> out

?

Кращим способом буде команда bash, Python також прийнятний, якщо не значно повільніше.


Оновлена ​​моя відповідь, findне сортує файли так само, як глобул оболонки.
— Graeme

5
Будь-які (розумні) рішення матимуть еквівалентну швидкість тут, оскільки час буде 99% системним введенням / виводом.
— золотинки


3
Розглянемо можливість запису зв'язаного файлу на інший диск, ніж той, який ви читаєте.
— Луїс

1
Це буде швидше, якщо outвін знаходиться на іншому диску.

Відповіді:


30

Ні, кішка, безумовно, найкращий спосіб це зробити. Навіщо використовувати python, коли для цієї програми вже написана програма на C? Однак ви, можливо, захочете скористатися xargsу випадку, якщо довжина командного рядка перевищує ARG_MAXі вам потрібно більше одного cat. Використовуючи інструменти GNU, це еквівалентно тому, що у вас вже є:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out

1
Чи можете ви в цьому випадку застрахувати, що ваші файли будуть прочитані в порядку?
— Ківі

1
Так, тому що вихідний сигнал findпроходить через sort. Без цього файли будуть перераховані у довільному порядку (визначеному файловою системою, який може бути порядком створення файлів).
— scai

@scai Вибачте, вибачте, начебто це досить очевидно
— Kiwy

1
@Kiwy, єдиний випадок, який я можу побачити, якщо локаль не встановлений належним чином у середовищі, то сортування може поводитись інакше, ніж у bashглобальній. Інакше я не бачу жодних випадків, коли б xargsчи catне поводилися б так, як очікувалося.
— Graeme

3
@MarcvanLeeuwen, xargsзателефонує наскільки це можливо cat, щоб уникнути помилки execve E2BIG (2).
— Стефан Шазелас

21

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

Наприклад, якщо в Linux:

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out

Ще одна перевага полягає в тому, що якщо не вистачає вільного місця, копія не буде здійснена.

Якщо увімкнено btrfs, ви можете copy --reflink=alwaysстворити перший файл (який не передбачає копіювання даних і тому був би майже миттєвим), а решту додати. Якщо є 10000 файлів, це, ймовірно, не матиме великої різниці, якщо тільки перший файл не дуже великий.

Існує API для узагальнення, щоб повторно скопіювати всі файли ( BTRFS_IOC_CLONE_RANGE ioctl), але я не зміг знайти жодної утиліти, яка розкривала б цей API, тому вам доведеться робити це на C ( pythonабо інших мовах за умови, що вони можуть викликати довільні ioctls) .

Якщо вихідні файли є рідкісними або мають великі послідовності символів NUL, ви можете створити розріджений вихідний файл (економія часу та дискового простору) за допомогою (у системах GNU):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out

1
@XTian, ​​ні, це не повинно бути ні >ні >>, але, 1<>як я вже сказав, записати у файл.
— Стефан Шазелас

5
@grebneke <>- це стандартний оператор переадресації читання + запису Bourne / POSIX. Докладніше див. Посібник із оболонки або специфікацію POSIX . Значення за замовчуванням fdє 0для <>оператора ( <>коротко для 0<>, як <коротко для 0<і >коротких для 1>), тому вам потрібно 1явно перенаправляти стандартний висновок. Тут справа не в тому, що нам потрібно читати + писати ( O_RDWR), а в тому, що ми не хочемо O_TRUNC(як у >), які б розбирали те, що ми тільки що виділили.
— Стефан Шазелас

1
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 дасть вам декілька. ksh93 має пошук операторів BTW, і ви можете шукати вперед за допомогою ddчи читання.
— Стефан Шазелас

1
@StephaneChazelas - велике спасибі, ваша допомога та знання глибоко вдячні!
— grebneke

1
Я не переконаний у тому, що буде багато випадків, коли fallocateзаперечуватимуть накладні витрати find, навіть якщо це буде швидше вдруге. btrfsЗвичайно, відкриваються цікаві можливості.
— Graeme
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.