Як шукати текст у всій файловій системі?


53

Припускаючи, що слід використовувати інструмент grep, я хотів би шукати текстовий рядок "800x600" у всій файловій системі.

Я намагався:

grep -r 800x600 /

але це не працює.

Що я вважаю, що моя команда повинна робити, - це рекурсивно виконувати всі файли / папки під коренем для тексту "800x600" та перераховувати результати пошуку.

Що я роблю неправильно?


2
І під "це не працює" ви маєте на увазі саме що? Чи не друкується якийсь вихід, зависає чи друкується багато Permission deniedпомилок? Ви запустили його як root або звичайний користувач?
alex

Я отримую деяку тягу, насамперед я опинився в домашньому каталозі свого користувача, намагаючись запустити команду. Отож, тепер я CD / Out для root. Далі я спробував таку ж команду, що і вище, і я отримую багато помилок, дозволених дозволено. Ок, тепер я спробую sudo grep -r 800x600 /, і тоді я отримую / proc / sysrq-тригер: Помилка вводу / виводу
Level1Coder

Хм, не знаю, чому це не спрацює. Ви можете ігнорувати помилки доступу, роблячи це grep -r 800x600 / 2>/dev/null. Ви також можете спробувати запустити його як root.
Тотор

Відповіді:


64

Я зазвичай використовую цей стиль команди для запуску grepдекількох файлів:

find / -xdev -type f -print0 | xargs -0 grep -H "800x600"

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

-xdevАргумент вказує виявити , що він повинен ігнорувати інші файлові системи - це добре для уникнення спеціальних файлових систем , таких як /proc. Однак він також ігнорує звичайні файлові системи - тому, якщо, наприклад, ваша / домашня папка знаходиться на іншому розділі, вона не буде шукана - вам потрібно буде сказати find / /home -xdev ....

-type fозначає лише пошук файлів, тому каталоги, пристрої та інші спеціальні файли ігноруються (він все одно повторюватиметься в каталогах та виконуватиметься grepу файлах всередині - він просто не буде виконуватись grepу самому каталозі, який би не працював у будь-якому разі). І -Hможливість grepсказати йому завжди друкувати ім'я файлу у своєму виході.

findприймає всілякі варіанти фільтрування списку файлів. Наприклад, -name '*.txt'обробляє лише файли, що закінчуються .txt. -size -2Mозначає файли розміром менше 2 мегабайт. -mtime -5означає файли, змінені за останні п’ять днів. Приєднуйтесь до них разом з -a для і -o для або і використовуйте '('круглі дужки ')'для групових виразів (у лапках, щоб оболонка не інтерпретувала їх). Так, наприклад:

find / -xdev '(' -type f -a -name '*.txt' -a -size -2M -a -mtime -5 ')' -print0 | xargs -0 grep -H "800x600"

Погляньте, man findщоб побачити повний список можливих фільтрів.


2
Зауважте, що -xdevбуде виключено всі інші файлові системи, а не лише спеціальні. (наприклад, якщо ви /homeвстановили окремий розділ, його не буде шукати.)
cjm

Я спробував запустити кожен, але обидва повертають помилку -find: paths must precede expression: /
Level1Coder

1
Примітка: Коли регулярні вирази не потрібні, "fgrep" значно швидше, ніж "grep", що призведе до великої різниці, якщо ви шукаєте велике дерево.
Nathan Kidd

1
Ви можете уникнути проходження xargsз, можливо, кращою ефективністю, роблячи це find / -xdev -type f -exec grep -H '800x600' +.
Тотор

3
Ні, +знак в кінці findкоманди насправді робить те саме, що xargs: породжує один grepпроцес з кількома аргументами.
Тотор

14

Зазвичай ви не хочете насправді шукати ВСЕ у системі. Linux використовує файлові вузли для всього, тому деякі "файли" - це не те, що ви хотіли б шукати. Наприклад /dev/sda, пристрій фізичного блоку для вашого першого жорсткого диска. Ймовірно, ви хочете шукати змонтовані файлові системи, а не пристрої із необробленим диском. Також є те, /dev/randomщо виплюває випадкові дані щоразу, коли ви їх читаєте. Пошук, який не має великого сенсу. /procФайлова система також є проблематичною в вашому випадку.

Я б рекомендував одну з двох речей.

  1. Не шукайте корінь, шукайте лише місця, які можуть бути корисними. Шукати /homeабо /usrабо /etcокремо. Інформація, яку ви шукаєте, швидше за все, конкретного типу, тому вона все одно буде знаходитися у певній папці. Параметри конфігурації повинні бути встановлені /etc. Ваші файли особистих даних повинні бути в /home. Обмеження пошуку до такої важливої ​​області значно зменшить ваші проблеми з рекурсивними помилками.

  2. Виключіть проблемні області, використовуючи --exclude-dirнабір речей, які вам не знадобляться:
    grep -r --exclude-dir /proc --exclude-dir /dev --exclude-dir /tmp --exclude-dir /lost+found

Нарешті, нечасто зустрічатися з декількома помилками, у яких відмовлено у дозволі, коли робиться велика рекурсивна помилка. Під час звичайного використання є файли, які ваш користувач може не в змозі прочитати. Поки це лише кілька непарних файлів, а не такі речі, як необроблений пристрій для ваших жорстких дисків або всієї файлової системи Proc, нормально просто ігнорувати помилки. Насправді ви можете зробити це в командному рядку, надіславши всі помилки, які ніколи не приземляються:

grep -r search_string /path 2> /dev/null

3
-Iвиключити двійкове
Рахул Патіл

2

Для простоти я б запропонував ack-grep . Посилання показує багато випадків, коли ack-grepце кращий варіант.

Використовувати це після встановлення:

ack-grep pattern /

Дякую, що рекомендували це, але я запустив це, і це насправді не дало мені результатів пошуку, які я очікував. Здається, мені потрібно буде налаштувати багато налаштувань, щоб отримати те, що я хочу. На сьогодні відповідь Річарда працює прямо з вікна. Ми розглянемо це в майбутньому, як це здасться і корисним.
Level1Coder


0

* тоді я отримую / proc / sysrq-тригер: помилка вводу / виводу

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

Я рекомендую виключити системні каталоги з

grep -exclude-dir = {proc, sys} "800x600" /


-3

просто правильно-

grep -r "800x600" /

-Що не так у вашій нинішній команді, це лапки, "". Завжди ставте аргумент рядка до grepлапок.


3
Тут не проблема. Вам не потрібні цитати, коли ви даєте саме цей тип аргументів grep. Спробуйте, і побачите. Помістіть рядок "800x600" у файл, і тоді grep 800x600 fileви побачите, що він працює чудово. ОП, очевидно, має інше питання.
slm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.