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


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.