У мене є 10 к + файлів на загальну суму понад 20 ГБ, які мені потрібно об'єднати в один файл.
Чи є швидший шлях, ніж
cat input_file* >> out
?
Кращим способом буде команда bash, Python також прийнятний, якщо не значно повільніше.
У мене є 10 к + файлів на загальну суму понад 20 ГБ, які мені потрібно об'єднати в один файл.
Чи є швидший шлях, ніж
cat input_file* >> out
?
Кращим способом буде команда bash, Python також прийнятний, якщо не значно повільніше.
Відповіді:
Ні, кішка, безумовно, найкращий спосіб це зробити. Навіщо використовувати python, коли для цієї програми вже написана програма на C? Однак ви, можливо, захочете скористатися xargsу випадку, якщо довжина командного рядка перевищує ARG_MAXі вам потрібно більше одного cat. Використовуючи інструменти GNU, це еквівалентно тому, що у вас вже є:
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z |
xargs -0 cat -- >>out
findпроходить через sort. Без цього файли будуть перераховані у довільному порядку (визначеному файловою системою, який може бути порядком створення файлів).
bashглобальній. Інакше я не бачу жодних випадків, коли б xargsчи catне поводилися б так, як очікувалося.
xargsзателефонує наскільки це можливо cat, щоб уникнути помилки execve E2BIG (2).
Виділення місця для вихідного файлу спочатку може покращити загальну швидкість, оскільки системі не доведеться оновлювати розподіл для кожного запису.
Наприклад, якщо в 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<>як я вже сказав, записати у файл.
<>- це стандартний оператор переадресації читання + запису Bourne / POSIX. Докладніше див. Посібник із оболонки або специфікацію POSIX . Значення за замовчуванням fdє 0для <>оператора ( <>коротко для 0<>, як <коротко для 0<і >коротких для 1>), тому вам потрібно 1явно перенаправляти стандартний висновок. Тут справа не в тому, що нам потрібно читати + писати ( O_RDWR), а в тому, що ми не хочемо O_TRUNC(як у >), які б розбирали те, що ми тільки що виділили.
ddчи читання.
fallocateзаперечуватимуть накладні витрати find, навіть якщо це буде швидше вдруге. btrfsЗвичайно, відкриваються цікаві можливості.
findне сортує файли так само, як глобул оболонки.