Як знайти підрядку у файлах у підкаталогах за допомогою однієї вбудованої команди?


10

У Windows, якби я хотів знайти рядок у всіх файлах у всіх підкаталогах, я б зробив щось подібне

findstr /C:"the string" /S *.h

Однак, в Linux (наприклад, Ubuntu) Я не знайшов іншого виходу , крім який - то централізованого команди з участю find, xargsі grep( в якості прикладу можна на цій сторінці: Як я можу рекурсивно Grep через підкаталогів ). Однак моє запитання інше: чи є якась одна вбудована команда, яка працює за допомогою цієї магії, без того, щоб писати мій сценарій оболонки?

Відповіді:


19

GNU grep дозволяє рекурсивно шукати через підкаталоги:

grep -r --include='*.h' 'the string' .

Я спробував цей точний командний рядок в Ubuntu, але отримав "grep: недійсний варіант -" M "", хоча я ніде не можу побачити "M" ... спантеличуючи
Guido Domenici

@Guido чудово працює тут
phunehehe

У запропонованому редагуванні TomasG рекомендує змінити останнє *на '*': "Цитування останньої підстановки потрібно, щоб уникнути помилок, коли якесь ім'я файлу починається з -"
Michael Mrozek

У дивному повороті подій він зараз працює і для мене, як це було зазначено в оригінальній відповіді. Дякую!
Guido Domenici

1
@Guido: Можливо, ваша проблема була пов’язана з файлом у поточній папці, що називається -Msomething, або з GREP_OPTIONSналаштуваннями.
Жил "ТАК - перестань бути злим"

2

grep -r searchpattern /path/to/start/in

Де /path/to/start/in/може бути просто " ." для поточного каталогу.


1

Ні. find -name \*.h -print0 | xargs -0 grep -l 'the regex'- це настільки ж магія, як це виходить.


GNU grep має вбудовані випадкові випадки з його -rможливістю. Не потрібно важкої артилерії.
Жил "ТАК - перестань бути злим"

3
xargsдодає просто шум. Використанняfind -name \*.h -execdir grep -l 'the regex {} +
користувач невідомий

0

чи є якась одна вбудована команда, яка працює завдяки цій магії ...?

Щоб бути педантичним, ні, ви не можете припустити, що така команда існує .

Існує багато різних реалізацій Unix, і кожна має свої особливості. POSIX, загальний знаменник (і найбільш близький до стандарту у Unices) не визначає такий варіант дляgrep .

Як вже згадувалося в інших відповідях, реалізація GNU grepмає нестандартний варіант, який робить те, що ви хочете. Хоча ця конкретна реалізація може бути поширеною в системах Linux, ви не можете припустити її доступність для будь-яких Unix, навіть деяких систем Linux.

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

У вашому випадку сканування файлової системи та відповідність регулярного виразу в потоці - це дві окремі задачі. Лише нормально ставитися до кожного в окремій програмі.


0

Щоб знайти рядок із заданого каталогу, використовуйте команду нижче

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Наприклад:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;

1
grepможе приймати більше аргументів як один аргумент, тому вам слід використовувати +замість того, \;щоб не запускати одне grepвиклик на файл, що є досить неефективним.
Стефан Хазелас

1
Зауважте, що -name '*'обмежується файлами, ім'я яких є дійсним текстом у поточному локалі ( findхоча б у деяких реалізаціях), але інші компоненти каталогу все ще можуть містити послідовності байтів, які не утворюють дійсних символів. Якщо ваш намір з цим -name '*'полягав у тому, щоб переконатися, що вихідний текст є дійсним (пропускаючи файли з неправильними іменами), ви бажаєте скористатисяfind ... ! -name '*' -prune -o -exec grep ... {} + , що також не зупиниться на findспуску в каталоги з неправильними іменами.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.