Питання Як знайти всі файли, що містять певний текст на Linux?


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

Коли я шукав, як це зробити, я двічі наткнувся на це рішення:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Однак це не працює. Схоже, відображається кожен файл у системі.

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


3693
2018-06-06 08:06


походження


пам'ятайте, що grep буде інтерпретувати будь-який . як одноколісний символ, серед інших. Моя порада полягає в тому, щоб завжди використовувати або fgrep, або egrep. - Walter Tross
У всякому разі, ти був майже там! Просто замініть -H з -l (і можливо grep з fgrep) Щоб виключити файли з певними шаблонами імен, які ви б використовували findбільш просунутий спосіб. Варто навчитися користуватися find, правда. Просто man find. - Walter Tross
find … -exec <cmd> + легше вводити і швидше, ніж find … -exec <cmd> \;. Це працює тільки якщо <cmd> приймає будь-яку кількість аргументів імені файлу. Економія часу виконання особливо велика, якщо <cmd> починає повільно, як сценарії Python або Ruby. - hagello
Для пошуку без рекурсивно на заданому шляху команда є `grep -include = *. Txt -snw" шаблон thepath / *. - Stéphane Laurent
@ StéphaneLaurent Я думаю, ви ускладнюєте це занадто багато. Просто сказати grep "pattern" path/*.txt - fedorqui


Відповіді:


Зробіть наступне:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -r або -R є рекурсивним
  • -n це номер рядка, а також
  • -w символізує матч ціле слово.
  • -l (нижній регістр L) можна додати, щоб просто вказати ім'я файлу відповідних файлів.

Поряд з цими --exclude, --include, --exclude-dir Прапори можуть бути використані для ефективного пошуку:

  • Це буде виконувати пошук лише за тими файлами, які мають розширення .c або .h:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • Це виключить пошук всіх файлів, що закінчуються розширенням .o.

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • Для каталогів можна виключити певний каталог (и) через --exclude-dir параметр Наприклад, це виключить dirs dir1 /, dir2 /, і всі вони відповідають * .dst /:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

Це дуже добре для мене, щоб досягти майже такої ж мети, як ваша.

Для отримання додаткових опцій перевірити man grep.


6681
2018-06-06 08:21



використання --виключити як "grep -rnw --exclude = *. o 'directory' -e" шаблон " - rakib_
Я вважаю параметр grep --include дуже корисним. Наприклад: grep -rnw --include = *. Java. - "все, що я шукаю" - Lucas A.
Варто відзначити: це здається r варіант лінивий (перетинає глибину-перше, ніж зупиняється після першого каталогу), while R є жадібним (буде правильно переходити все дерево). - Eliran Malka
Примітка (особливо для новачків): важливі котирування у наведеній вище команді. - madD7
@ Еліран Малка R en r буде обидва рухати каталоги правильно, але R буде слідувати символічним посиланням. - bzeaman


Ви можете використовувати grep -ilR:

grep -Ril "text-to-find-here" /
  • i означає випадк ігнорування (необов'язково у вашому випадку).
  • R означає рекурсивний.
  • l означає "показати ім'я файлу, а не сам результат".
  • / означає почати від кореня вашої машини.

1087
2018-06-06 08:08



На основі мого досвіду, -i сповільнює його, тому не використовуйте його, якщо це не обов'язково. Перевірте його в певному режимі, а потім узагальнюйте. Його потрібно заповнити протягом декількох хвилин. Я думаю, що регулярний вираз полегшить його. Але мої коментарі базуються на припущеннях, я пропоную вам протестувати його time перед лінією - fedorqui
так, /* це означає. У будь-якому випадку я просто протестував і помітив це просто / працює - fedorqui
Якщо ви не здійснюєте пошук за допомогою регулярного виразу, ви можете використовувати fgrep замість grep у більшості систем. - markle976
Так @ markle976, насправді від людини grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings. - fedorqui
Ви можете замінити / з шляху до каталогу grep -Ril "text-to-find-here" ~/sites/ або використовувати. для поточного каталогу grep -Ril "text-to-find-here" . - Black


Ви можете використовувати акк. Це схоже grep для вихідного коду. Ви можете сканувати всю свою файлову систему.

Просто:

ack 'text-to-find-here'

У вашому кореневому каталозі.

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


UPDATE

Я щойно відкрив Срібний дослідник, який виглядає як ACK, але 3-5x швидше, ніж це, і навіть ігнорує шаблони від a .gitignore файл


234
2018-06-06 08:26



Дуже корисно, просто і швидко. Попередження: "В дистрибутивах, отриманих від Debian, ack упакований як" ack-grep ", оскільки" ack "вже існував" (від beyondgrep.com/install) Ви можете в кінцевому підсумку запустити конвертер коду Kanji на цих Linux ... - Jose_GD
ack або ack-grep має приємні висвітлення, але знайти + grep, коли належним чином використовується набагато краще в продуктивності - Sławomir Lenart
Зауважте, що ripgrep це швидше, ніж будь-що інше, що згадується тут, у тому числі "Срібний дослідник" і просто "Ол ГРП". Побачити це повідомлення в блозі за доказ. - Radon Rosborough


Ви можете використовувати:

grep -r "string to be searched"  /path/to/dir

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

Або команда, аналогічна тому, що ви намагаєтесь (наприклад:) для пошуку у всіх файлах javascript (* .js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

Це буде друкувати рядки у файлах, де текст з'являється, але не друкує ім'я файлу.

На додаток до цієї команди ми можемо також написати це: grep -rn "Строка для пошуку" / path / to / directory / або / file -r: рекурсивний пошук n: номер рядка буде показано для матчів


126
2018-03-14 23:29



Thanx для пошукової версії. Моя версія grep (busybox для NAS) не має параметра -r, я дійсно потребував іншого рішення! - j.c
Дякую за версію "знайти"! Настільки важливо мати можливість фільтрувати ".js "або". txt "і т. д. Ніхто не хоче витрачати багато годин, чекаючи, що Grep завершить пошук у всіх мультигігабайтних відео з останнього сімейного відпочинку, навіть якщо команду легше вводити. - mightypile


Ви можете використовувати це:

grep -inr "Text" folder/to/be/searched/

83
2017-07-31 13:44



Найпростіший, докладний, рекурсивний і нечутливий до регістру. пальці вгору. - Francesco Casula
якщо додати -A3 ще краще - albanx
Це дуже круто. - kodmanyagha


Список імен файлів, що містять заданий текст

Перш за все, я вважаю, що ви використовували -H замість -l. Також ви можете спробувати додати текст в котирування, а потім {} \.

find / -type f -exec grep -l "text-to-find-here" {} \; 

Приклад

Скажімо, ви шукаєте файли, що містять певний текст "Ліцензія Apache" у вашому каталозі. Він покаже результати, подібні до нижче (результати будуть різними залежно від вмісту вашого каталогу).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Видаліть чутливість до випадку

Навіть якщо ви не користуєтеся справою, як "текст" або "TEXT", ви можете скористатись -i переключитися на ігнорування випадку. Ви можете ознайомитись з детальною інформацією тут.

Сподіваюсь, це допоможе вам.


50
2017-11-09 13:18



OP попросив файли, які містять текст у вмісті, а не імені файлу. - Auxiliary
Що таке ця команда: find пройде всі шляхи, які він знаходить для команди grep -l "text-to-find-here" <file found>". Ви можете додати обмеження до імені файлу, наприклад, find / -iname "*.txt" шукати тільки в файлах, назви яких закінчуються .txt - Mene
@Auxiliary - включений зразок виходу, щоб уникнути будь-яких плутанини для читачів. - lkamal
@Mene Це справді сумний стан, що коментар допоміжних органів має більше голосів, ніж твій ... навіть якщо їх коментар з 2014 року, і ваш 2017 рік, що їх коментар має 6, коли він повинен мати рівно 0, а ваш тільки один (тепер два) isn Не те, що я хотів би повірити. - Pryftan
@ Мене це сказано -iname є незалежним від регістру, що означає, що він також знайде файли .TXT, наприклад, TxT і TXT і так далі. - Pryftan


Якщо ти grep не підтримує рекурсивний пошук, ви можете об'єднати find з xargs:

find / -type f | xargs grep 'text-to-find-here'

Я вважаю це легше запам'ятати ніж формат для find -exec.

Це дасть назву файлу та вміст відповідної лінії, наприклад,

/home/rob/file:text-to-find-here

Необов'язкові прапорці, які ви можете додати до grep:

  • -i - бездокументарний пошук
  • -l - виводити тільки ім'я файлу, де було знайдено відповідність
  • -h - виводити тільки відповідну лінію (не ім'я файлу)

47
2018-06-20 08:49



Це еквівалентно grep 'text-to-find-here' без імені файлу, якщо find нічого не знайде. Це буде зависати і чекати введення користувача! Додати --no-run-if-empty як можливість xargs. - hagello
Ця комбінація пошуку та xargs не працює, як передбачається, якщо назви файлу або каталогу містять пробіли (символи, які xargs інтерпретує як роздільники). Використовуйте find … -exec grep … +. Якщо ви наполягаєте на використанні пошуку разом із xargs, використовуйте -print0 і -0. - hagello


grep -insr "pattern" *
  • i: Ігнорувати випадкові відмінності як в PATTERN, так і у вхідних файлах.
  • n: Префікс кожного рядка виводу з номером рядка на основі 1 у його вхідному файлі.
  • s: Приховування повідомлень про неіснуючі або нечитаемые файли.
  • r: Прочитайте всі файли в кожному каталозі, рекурсивно.

34
2018-02-26 05:47



Чи можете ви пояснити, як ваша відповідь покращується на інші відповіді, або як вона достатньо відрізняється від них? - Amos M. Carpenter
не складно запам'ятати, буде охоплювати всі шаблони (case-senstivity -> off, включає назви файлів і номер рядка і буде робити рекурсивний пошук тощо) і, використовуючи "*", в кінці буде шукати всі каталоги (не потрібно вказувати будь-яку назва шляху або каталогу). - enfinet
На жаль, я мав краще зрозуміти: було б здорово, якщо б ви могли включити це пояснення у ваш відповідь. Оскільки він стоїть, особливо з таким числом інших подібних відповідей, важко побачити з такої короткої відповіді, яка користь намагатися це над прийнятою відповіддю або однією з вищезгаданих буде. - Amos M. Carpenter
Це гарна відповідь + хороше пояснення - khelili miliana
@ AmosM.Carpenter Одне, що я люблю в цій відповіді, вказує на придушення аргументу, який може допомогти відфільтрувати шум, який не має значення для отримання результатів, які ми насправді хочемо. Grep виводить на "" файли "помилки" Функція не реалізована "," Недійсний аргумент "," Ресурс недоступний "тощо. - leetNightshade


grep (GNU або BSD)

Ви можете використовувати grep інструмент для рекурсивного пошуку поточної папки, наприклад:

grep -r "class foo" .

Примітка: -r - рекурсивно шукати підкаталоги.

Ви також можете використовувати синтаксис globing для пошуку в певних файлах, таких як:

grep "class foo" **/*.c

Примітка: Використовуючи галобінг варіант (**), він сканує всі файли рекурсивно з певним розширенням або шаблоном. Щоб увімкнути цей синтаксис, запустіть: shopt -s globstar. Ви також можете використовувати **/*.* для всіх файлів (за винятком прихованих і без розширення) або будь-якого іншого шаблону.

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

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Альтернативно можна використовувати ripgrep.

ripgrep

Якщо ви працюєте над великими проектами або великими файлами, ви повинні використовувати ripgrep замість цього:

rg "class foo" .

Оформити документи, етапи встановлення або вихідний код на Сторінка проекту GitHub.

Це набагато швидше, ніж будь-який інший інструмент, як GNU/BSD  grep, ucg, ag, sift, ack, pt або подібний, оскільки він побудований на вершині Регукс двигун іржі яка використовує кінцеві автомати, SIMD та агресивну буквальну оптимізацію для швидкого пошуку.

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


Ви можете використовувати загальні параметри, такі як:

  • -i - Нечутливий пошук.
  • -I - Ігнорувати бінарні файли.
  • -w - Пошук цілих слів (на відміну від часткового співпадіння слів).
  • -n - Показувати лінію вашого матчу.
  • -C/--context (наприклад, -C5) - Збільшує контекст, тому ви бачите навколишній код.
  • --color=auto - Позначте відповідний текст.
  • -H - Відображає ім'я файлу, де знаходиться текст.
  • -c - Відображає кількість відповідних ліній. Можна поєднати з -H.

29
2018-05-09 10:11



Я також вважаю корисним розширений шаблон. Але майте на увазі, що якщо дійсно величезна кількість файлів, ви можете отримати помилку "Аргумент занадто довгий". (Простий глобінг також схильний до такого роду помилки). - Yoory N.