Як я грепкую рекурсивно?


1682

Як зробити рекурсивно grepвсі каталоги та підкаталоги?

find . | xargs grep "texthere" *

110
@ TC1 Сумно в тому, що grep сам може відповісти на питання (принаймні GNU grep): grep --help | grep рекурсивний
Frank Schmitt

7
Якщо ви часто використовуєте grep для рекурсивного пошуку (особливо якщо ви вручну робите багато винятків файлів / каталогів), вам може бути корисний ack (дуже зручна для програмістів альтернатива grep).
Нік МакКерді

19
Насправді ні -r, ні - рекурсивна робота на полі Solaris, який я використовую на роботі. І сторінка man для grep не згадує нічого рекурсивного. Мені довелося вдатися, щоб знайти і надіслати себе.
Бен

8
ag - це мій улюблений спосіб це зробити зараз github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plне працює для мене на Redhat Linux. Я отримую помилку "без збігу"
Bulrush

Відповіді:


2507
grep -r "texthere" .

Перший параметр являє собою регулярний вираз для пошуку, а другий - каталог, який слід шукати. У цьому випадку .означає поточний каталог.

Примітка. Це працює для GNU grep, і на деяких платформах, таких як Solaris, ви повинні спеціально використовувати GNU grep на відміну від застарілої реалізації. Для Solaris це ggrepкоманда.


39
Примітка: "grep -r" працює лише на новіших зображеннях. Він не працює на греп, який поставляється, AIX 5.3наприклад.
Затримано

110
Використовуйте grep -R для переходу до символьних посилань.
Елофф

53
Добре знати, що "-i" зробить це випадково нечутливим, а "-n" також включить номер рядка для кожного відповідного результату.
Садег

24
також добре знати, якщо ви просто шукаєте фіксовану рядок, а не регулярний вираз, використовуйте опцію -F. це допоможе вам заощадити час, не викликаючи аналізатор регулярних виразів. дуже зручно, якщо ви шукаєте безліч файлів.
Джефф

6
псевдонім rgrep = 'grep -r'
totten

679

Якщо ви знаєте розширення або шаблон файлу, який ви хочете, іншим методом є використання --includeопції:

grep -r --include "*.txt" texthere .

Ви також можете згадати файли, які потрібно виключити --exclude.

Ag

Якщо ви часто шукаєте код, Ag (The Silver Searcher) - це набагато швидша альтернатива grep, яка налаштована для пошуку коду. Наприклад, він за замовчуванням є рекурсивним і автоматично ігнорує файли та каталоги, перелічені в .gitignore, тому вам не доведеться продовжувати передавати ті самі громіздкі параметри виключення, щоб отримати копію або знайти.


3
Чудово працює з grep, який постачається з Linux та Cygwin, але не з тим, що постачається з AIX.
Затримано

1
@KrzysztofWolny: `` замість =роботи на Ubuntu працює чудово. PS: це повинно бути відтворений простір, але аналізатор розмітки SO не вдався.
Дан Даскалеску

4
@DanDascalescu Я виступив за grep, а не за агента , просто так ви знаєте :)
Бернхард

1
Чи є у нас можливість виключити каталог під час рекурсивного пошуку?
Том Тейлор

Windows cygwin любить подвійні цитати--include "*.txt" --include "*.TXT"
Боб Штейн

127

Також:

find ./ -type f -print0 | xargs -0 grep "foo"

але grep -rце краща відповідь.


14
Або якщо ви не хочете турбуватися про пробіли у назви файлів, find . -type f -exec grep "foo" '{}' \;добре працює там, де підтримується.
Edd Steel

4
Якщо ви збираєтесь знайти трубу через xargs для grep, І якщо ви шукаєте лише фіксовану рядок (тобто не регулярний вираз), ви можете скористатись опцією Grep -F, тому grep не завантажить двигун регулярного вираження. для кожного виклику. Якщо файлів багато, це буде набагато швидше.
Джефф

2
знайти. -тип f -exec grep -Hu "foo" {} \; це те, що я використовую, оскільки воно дає ім'я файлу.
Уес

Це працює на всіх * nix, тому що це POSIX 7
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke

118

Зараз я завжди використовую (навіть у Windows з GoW - Gnu в Windows ):

grep --include="*.xxx" -nRHI "my Text to grep" *

Це включає наступні варіанти:

--include=PATTERN

Повторюйте в каталогах лише пошук відповідності файлів PATTERN.

-n, --line-number

Префікс кожного рядка виводу з номером рядка у вхідному файлі.

(Примітка: phuclv додає в коментарях, що -nзначно знижує продуктивність , тому ви можете пропустити цю опцію)

-R, -r, --recursive

Читати всі файли в кожному каталозі, рекурсивно; це рівнозначно -d recurseваріанту.

-H, --with-filename

Роздрукуйте назву файлу для кожного матчу.

-I     

Обробляйте двійковий файл так, ніби він не містить відповідних даних;
це рівнозначно --binary-files=without-matchваріанту.

І я можу додати " i" ( -nRHIi), якщо хочу результати, що не залежать від регістру.

Я можу дістати:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow виглядає багатообіцяючим - новішим, ніж утиліти GNU Windows, якими я користувався. Спробуйте зараз ...
Радім Черней

яке значення останнього символу * тут?
lorniper

2
@lorniper, це змушує оболонку вибирати всі файли та папки у вашому поточному каталозі, завдяки чому grep застосовується до цих файлів і (рекурсивно через -Rопцію) до папок.
VonC

2
@lorniper Ной точно: *або .це глобальний зразок (інтерпретується оболонкою): unix.stackexchange.com/a/64695/7490 . ' .' також вибере точкові файли або папки з крапками (як .git/)
VonC

раніше я завжди використовував, grep -rnIале потім я дізнався, що -nзначно знижує продуктивність, тому я просто використовую її, коли це дійсно потрібно, і зазвичай я буду користуватися-rI
phuclv

25

В системах POSIX ви не знайдете -rпараметр для grepі grep -rn "stuff" .не запуститься, але якщо використовувати findкоманду, це:

find . -type f -exec grep -n "stuff" {} \; -print

Погоджено Solarisта HP-UX.


яке значення {} \; -віддрукувати відповідно?
користувач1169587

3
У -execваріанті - символ {}- це посилання на ім'я файлу, яке зараз знайдено findінструментом (тобто зробити щось із знайденим нами ім'ям файлу), також -execопцію слід припинити ;символом (щоб позначити закінчення команд виконувати), але тому, що це все Запуск у оболонці цього символу слід уникати .. і нарешті -printопція дозволяє findінструменту друкувати знайдені імена файлів на екрані.
грак

19

глобус **

Використання grep -rробіт, але це може бути надмірним, особливо у великих папках.

Для більш практичного використання ось синтаксис, який використовує синтаксис глобалізації ( **):

grep "texthere" **/*.txt

який збирає лише певні файли з обраним малюнком. Він працює для підтримуваних оболонок, таких як Bash +4 або zsh .

Щоб активувати цю функцію, виконайте команду: shopt -s globstar.

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

git grep

Для проектів під контролем версій Git використовуйте:

git grep "pattern"

що набагато швидше.

ripgrep

Для більш великих проектів найшвидший інструмент прихватування - це те, ripgrepщо файли файлів репресивно за замовчуванням:

rg "pattern" .

Він побудований на базі регекс-двигуна Руста, який використовує кінцеві автомати, SIMD та агресивні буквальні оптимізації, щоб зробити пошук дуже швидким. Перевірте детальний аналіз тут .


3
Дякую за пропозицію git grep - це дуже корисно, і я про це не знав!
Бася

2
Дякуємо за пропозицію про розрив. Це швидше.
Що було б круто

11

Щоб знайти ім'я filesз pathрекурсивно містить конкретну stringкоманду нижче, використовуйте для UNIX:

find . | xargs grep "searched-string"

для Linux:

grep -r "searched-string" .

знайти файл на UNIXсервері

find . -type f -name file_name

знайти файл на сервері LINUX

find . -name file_name


10

Якщо ви хочете лише переглядати фактичні каталоги, а не символічні посилання,

grep -r "thingToBeFound" directory

Якщо ви хочете переходити як до символьних посилань, так і до фактичних каталогів (будьте уважні до нескінченної рекурсії),

grep -R "thing to be found" directory

Оскільки ви намагаєтесь рекурсивно відстукувати, наступні варіанти також можуть бути корисними для вас:

-H: outputs the filename with the line

-n: outputs the line number in the file

Отже, якщо ви хочете знайти всі файли, що містять Darth Vader, у поточному каталозі чи будь-яких підкаталогах та захопити ім'я файлу та номер рядка, але не хочете, щоб рекурсія переходила до символічних посилань, команда буде

grep -rnH "Darth Vader" .

Якщо ви хочете знайти в каталозі всі згадки про слово кішка

/home/adam/Desktop/TomAndJerry 

і ви зараз в каталозі

/home/adam/Desktop/WorldDominationPlot

і ви хочете захопити ім'я файлу, але не номер рядка будь-якого екземпляра рядка "cats", і ви хочете, щоб рекурсія переходила до символічних посилань, якщо вона їх знайде, ви можете запустити будь-яке з наведених нижче

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

Джерело:

працює "grep --help"

Короткий вступ до символічних посилань, для тих, хто читає цю відповідь та збентежений моїм посиланням на них: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Чудова відповідь. Додаткові комутатори (-rnh) дуже корисні, тому дякую, що запропонували їх.
semtex41

8

ag - це мій улюблений спосіб зробити це зараз github.com/ggreer/the_silver_searcher . Це в основному те саме, що і ack, але з кількома оптимізаціями.

Ось короткий орієнтир. Я очищаю кеш перед кожним тестом (див. Https://askubuntu.com/questions/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

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

find -type f -exec grep -l "texthere" {} +

Зауважте, що -l(в нижньому регістрі L) відображається назва файлу, який містить текст. Видаліть його, якщо натомість хочете роздрукувати сам збіг. Або скористайтеся, -Hщоб отримати файл разом із збігом. Всі разом, інші альтернативи:

find -type f -exec grep -Hn "texthere" {} +

Де -nдрукується номер рядка


2
Up проголосували за те , що єдиним findрішенням як уникнути непотрібних використання xargsі використовувати +замість \;з -exec, тим самим уникаючи тонни непотрібних запусків процесу. :-)
ShadowRanger

6

Це той, хто працював у моєму випадку на моїй поточній машині (git bash на Windows 7):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

Я завжди забуваю -принт0 і -0 для шляхів з пробілами.

EDIT: Мій улюблений інструмент зараз замість ripgrep: https://github.com/BurntSushi/ripgrep/releases . Це дійсно швидко і має кращі значення за замовчуванням (наприклад, рекурсивні за замовчуванням). Такий же приклад, як і моя оригінальна відповідь, але з використанням ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (термін повідомлення наприкінці)

(^ кредит: https://stackoverflow.com/a/1987928/1438029 )


Пояснення:

grep -r "texthere" /(рекурсивно знімайте всі каталоги та підкаталоги)

grep -r "texthere" .(рекурсивно знімайте ці каталоги та підкаталоги)

греп рекурсивний

grep [options] PATTERN [FILE...]

[параметри]

-R, -r, --recursive

Читайте всі файли в кожному каталозі, рекурсивно.

Це еквівалентно варіанту -d recurseабо --directories=recurse.

http://linuxcommand.org/man_pages/grep1.html

греп допомогу

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

Альтернативи

ack( http://beyondgrep.com/ )

ag( http://github.com/ggreer/the_silver_searcher )


4

У 2018 році ви хочете використовувати ripgrepабо the-silver-searcherтому, що вони набагато швидші за альтернативи.

Ось каталог із 336 підкаталогами першого рівня:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

На OSX, це встановлює ripgrep: brew install ripgrep. Це встановлює silver-searcher: brew install the_silver_searcher.


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

Мені здається, що програміст шукає текст у вихідному дереві лише кілька разів на рік. Але навіть з точки зору зручності використання, rgвона має значну перевагу над обмотуванням разом рекурсивної команди grep з нуля. Використання rg: rg foo. Використання інструментів Unix: find . | xargs grep foo. І якщо в будь-якому з ваших файлів є цитата, вам потрібно скористатися find . -print0 | xargs -0 grep foo. Чи пам’ятаєте ви про це, якщо користуєтесь цим кілька разів на рік?
hughdbrown

1
Ви забуваєте, find . -type f -exec grep 'regex' {} +що насправді легко запам'ятати, якщо ви використовуєте ці інструменти з будь-якою регулярністю. Але, мабуть, вам слід все-таки запуститись ctagsабо etagsна вихідному дереві, якщо вам потрібно часто знаходити матеріали.
tripleee

Я використовую ріпгреп, і це чудово. Але срібний шукач фантастичний для програмістів. +1
Метт

3

У моєму сервері IBM AIX (версія ОС: AIX 5.2) використовуйте:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

це дозволить роздрукувати шлях / ім'я файлу та відносний номер рядка у файлі, як:

./inc/xxxx_x.h

2865: / ** Опис: stringYouWannaFind * /

все одно, це працює для мене:)


3

Нижче наведено команду для пошуку Stringрекурсивно в середовищі Unixта Linuxоточенні.

для UNIXкоманди є:

find . -name "string to be searched" -exec grep "text" "{}" \;

для Linuxкоманди є:

grep -r "string to be searched" .

2

Список доступних прапорів:

grep --help 

Повертає всі збіги для текстового поля регулярного виразів у поточному каталозі з відповідним номером рядка:

grep -rn "texthere" .

Повертає всі збіги для texthere , починаючи з кореневого каталогу, з відповідним номером рядка та ігноруючи регістр:

grep -rni "texthere" /

тут використовуються прапори:

  • -r рекурсивний
  • -n номер рядка для друку з виходом
  • -i ігнорувати випадок

1

Я думаю, це те, що ти намагаєшся написати

grep myText $(find .)

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

grep myText $(find .) | cut -d : -f 1 | sort | uniq

Це дуже інтуїтивно: наприклад: grep -i acc $ (find. -Name "виконання *. *")
Ю. Шень

1

Кинув сюди два мої центи. Як вже згадували інші, grep -r працює не на кожній платформі. Це може здатися дурним, але я завжди використовую git.

git grep "texthere"

Навіть якщо каталог не є поетапним, я просто сформулюю його і використовую git grep.


0

Зауважте, що find . -type f | xargs grep whateverрізноманітні рішення потраплятимуть до помилок "Список аргументів на довгі", коли занадто багато файлів, які відповідають пошуку.

Найкраща ставка, grep -rале якщо такої немає, скористайтеся find . -type f -exec grep -H whatever {} \;натомість.


Так? xargsконкретно вирішує проблему "Аргумент надто довгий".
трійчатка

2
Ну, ні - xargs призначений спеціально для перетворення масиву аргументів у аргумент, але так, це правда, що сучасні xargs при використанні з -s та / або -L можуть мати справу з дуже довгими arlists, розбиваючись на кілька викликів команд, але він не налаштований таким чином за замовчуванням (і не було в жодному з вищезазначених відповідей). Як приклад:find . -type f | xargs -L 100 grep whatever
m.thome

На якій платформі це було б? POSIXxargs стандартизований для виведення такої поведінки поза коробкою. " xargsУтиліта повинна обмежувати довжину командного рядка таким чином, що коли викликається командний рядок, комбіновані списки аргументів та середовища ... не повинні перевищувати {ARG_MAX} -2048 байт."
трійчатка

Гм. Хоча на цій основі документи gnu менш зрозумілі, ніж posix, і я більше не маю доступу до машини, яка змусила мене зробити цю заяву, я не можу підтвердити своє оригінальне тлумачення щодо будь-якої поточної реалізації. Рекурсивна grep, звичайно, все ще є кращою, якщо вона є, але мало підстав уникати рецепту xargs (використовуйте -H для grep, щоб уникнути остаточного виклику грепу, який передається лише одним ім'ям файлу).
m.thome

0

Просто для задоволення, швидкий і брудний пошук файлів * .txt, якщо відповідь @christangrant занадто велика, щоб набрати :-)

grep -r texthere .|grep .txt


0

Ось рекурсивна (злегка перевірена з bash та sh) функція, яка обходить всі папки в заданій папці ($ 1) та використовує grepпошук по заданому рядку ($ 3) у заданих файлах ($ 2):

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

Запуск його та приклад виводу:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .

7
Це не додає багато інших відповідей
Мел
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.