Зібрати кілька тисяч файлів


13

У мене є каталог із cca 26 000 файлами, і мені потрібно поздоровитись у всіх цих файлах. Проблема полягає в тому, що мені це потрібно якомога швидше, тому не ідеально робити скрипт, де grep візьме ім'я одного файлу з команди find і запише збіги у файл. Перед тим, як видавати "список аргументів занадто довгий", для того, щоб зібрати всі ці файли, знадобилося близько 2 хвилин. Будь-які ідеї, як це зробити? редагувати: є сценарій, який створює нові файли весь час, тому неможливо розміщувати всі файли на різних сайтах.


1
використовувати findз xargsабоgrep -R
Eddy_Em

Це працює добре, але це займає 10 хвилин ...
user2778979

Відповіді:


19

З find:

cd /the/dir
find . -type f -exec grep pattern {} +

( -type fце пошук лише у звичайних файлах (також виключаючи символьні посилання, навіть якщо вони вказують на звичайні файли). Якщо ви хочете шукати в будь-якому типі файлів, крім каталогів), але будьте обережні, деякі файли типу fifos або / dev / zero як правило, ви не хочете читати), замініть -type fна специфічний для GNU ! -xtype d( -xtype dвідповідає файлам каталогу типів після роздільної здатності symlink)).

З GNU grep:

grep -r pattern /the/dir

(але майте на увазі, що якщо у вас є остання версія GNU grep, це буде слідувати посиланнями під час сходу в каталоги). Нерегулярні файли не будуть шукатись, якщо ви не додасте -D readпараметр. Останні версії GNU grepвсе ще не будуть шукати всередині посилань.

Дуже старі версії GNU findне підтримували стандартний {} +синтаксис, але там ви можете використовувати нестандартні:

cd /the/dir &&
  find . -type f -print0 | xargs -r0 grep pattern

Виступи, ймовірно, пов'язані введенням / виводом. Це час для пошуку був би час, необхідний для того, щоб прочитати всі ці дані зі сховища.

Якщо дані знаходяться на надлишковому масиві диска, читання декількох файлів одночасно може покращити продуктивність (і може погіршити їх інакше). Якщо виконання не пов'язане введенням / виведенням (оскільки, наприклад, всі дані знаходяться в кеші), а у вас є декілька процесорів, одночасно grepsможе допомогти і одночасно . Ви можете зробити це з допомогою GNU xargs«s -Pваріанту.

Наприклад, якщо дані знаходяться на масиві RAID1 з 3 дисками, або якщо дані знаходяться в кеші, і у вас є 3 процесора, час для збереження яких:

cd /the/dir &&
  find . -type f -print0 | xargs -n1000 -r0P3 grep pattern

(тут використовується -n1000для нерестування нових grepкожні 1000 файлів, до 3 одночасно працюючих).

Однак зауважте, що якщо результат grepперенаправлення, ви отримаєте погано переплетений вихід із трьох grepпроцесів, і в цьому випадку ви можете запустити його як:

find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern

(на останніх системах GNU або FreeBSD) або скористайтеся --line-bufferedопцією GNU grep.

Якщо patternце фіксований рядок, додавання -Fпараметра може покращити питання.

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

cd /the/dir &&
  LC_ALL=C grep -r pattern .

може значно покращити продуктивність

Якщо ви часто шукаєте такі пошукові запити, можливо, ви можете проіндексувати свої дані за допомогою однієї з багатьох пошукових систем там.


3

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

Виклик findне може пояснити низьку продуктивність, якщо ви не зробите це неправильно. Це швидкий спосіб переходу до каталогу та забезпечення того, що ви не ризикуєте здійснити занадто довгий командний рядок. Переконайтеся, що ви використовуєте -exec grep PATTERN {} +, яке запаковує стільки файлів, скільки може на виклик команди, а ні -exec grep PATTERN {} \;, який виконується grepодин раз на файл: виконання команди один раз на файл, ймовірно, буде значно повільніше.


Дякую, я щось пробуду в Google, і, мабуть, розберу це. Я зробив саме те, про що ви пишете, і це зайняло в 3 рази довше, ніж лише grep ...
user2778979

Жилле, ти кажеш, що продуктивність суттєво відрізнятиметься для 26000 файлів в одному каталозі проти 26 000 файлів, розповсюджених, скажімо, в 100 каталогах?
user001

1
@ user001 Так. Наскільки вони різняться, залежить від файлової системи та, можливо, від базового сховища, але я б очікував, що будь-яка файлова система може бути помірно швидшою з 260 файлами в кожному з 100 каталогів порівняно з 26000 файлами в одному каталозі.
Жил "ТАК - перестань бути злим"

Дякуємо за роз’яснення. Я поставив запитання щодо цього питання, щоб зрозуміти основу розбіжності.
user001

0

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

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


Як було зазначено в іншому місці, це не допомагає тому, що є занадто багато файлів для запуску grep. Існує також сенс, що: "є сценарій, який створює нові файли весь час, тому неможливо розмістити всі файли в різні режими".
Jeff Schaller

-2

Усі файли в каталозі

grep 'search string' *

з рекурсивно

grep -R 'search string' *

Потрібно розробити -1?
Маркус

4
Я не заявив, але є кілька проблем з вашим: ОП згадала "аргументаційний список занадто довгий", який ваш перший не виправить і, ймовірно, те, що робила ОП раніше. Другий не допомагає ні в цьому плані (допоміг би, якби ти використовував .замість цього *). *буде виключати крапкові файли (хоча і з -R, а не ті, у повторюваних каталогах). -R на відміну від -r слід посилань навіть на останніх версіях GNU grep. Ви також матимете проблеми з файлами у поточному каталозі, з якого починається ім’я-
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.