Как я могу grep рекурсивно?


1682

Как мне рекурсивно grepвсе каталоги и подкаталоги?

find . | xargs grep "texthere" *

110
@ TC1 Печально то, что сам grep может ответить на вопрос (по крайней мере, GNU grep): grep --help | рекурсивный grep
Фрэнк Шмитт

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

19
На самом деле ни -r, ни --recursive не работают на коробке Solaris, которую я использую на работе. И страница руководства для grep не упоминает ничего рекурсивного. Я должен был прибегнуть, чтобы найти и xargs сам.
Бен

8
ag - мой любимый способ сделать это сейчас github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plу меня не работает на Redhat Linux. Я получаю ошибку "нет совпадения".
камыш

Ответы:


2507
grep -r "texthere" .

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

Примечание: это работает для GNU grep, и на некоторых платформах, таких как Solaris, вы должны специально использовать GNU grep, а не устаревшую реализацию. Для Соляриса это ggrepкоманда.


39
Примечание: «grep -r» работает только на новых greps. Это не работает на grep, который идет с, AIX 5.3например.
Удержан

110
Используйте grep -R, чтобы следовать символическим ссылкам.
Eloff

53
Полезно знать, что «-i» делает его нечувствительным к регистру, а «-n» также включает номер строки для каждого соответствующего результата.
Садег

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

6
псевдоним rgrep = 'Grep -r'
Тоттен

680

Если вы знаете расширение или шаблон файла, который вам нужен, другой способ - использовать --includeпараметр:

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

Вы также можете упомянуть файлы, которые нужно исключить --exclude.

Ag

Если вы часто просматриваете код, Ag (The Silver Searcher) - гораздо более быстрая альтернатива grep, настроенная для поиска кода. Например, по умолчанию он рекурсивный и автоматически игнорирует файлы и каталоги, перечисленные в нем .gitignore, поэтому вам не нужно постоянно передавать одни и те же громоздкие параметры исключения для grep или find.


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" '{}' \;хорошо работает там, где поддерживается.
Эдд Стил

4
Если вы собираетесь передать поиск через xargs в grep, И если вы ищете только фиксированную строку (т. Е. Не регулярное выражение), вы могли бы извлечь выгоду из вызова опции grep -F, поэтому grep не будет загружать механизм регулярных выражений за каждый вызов. Если файлов много, это будет намного быстрее.
Джефф

2
найти . -type 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 Noy точно: *или .шаблон глобуса (интерпретируется оболочкой): 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.


Каково значение {} \; -принт соответственно?
user1169587

3
В -execопции - символ {}- это ссылка на имя файла, которое в данный момент найдено findинструментом (то есть что-то сделать с найденным нами именем файла), также -execопция должна заканчиваться ;символом (для обозначения окончания команд exec), но поскольку это все при запуске в оболочке этот символ должен быть экранирован ... и, наконец, -printопция позволяет findинструменту распечатывать найденные имена файлов на экране.
Ладья

19

подстановка **

Использование grep -rработает, но это может перебить, особенно в больших папках.

Для более практического использования, вот синтаксис, который использует синтаксис globbing ( **):

grep "texthere" **/*.txt

который greps только определенные файлы с шаблоном выбранного шаблона. Это работает для поддерживаемых оболочек, таких как Bash +4 или Zsh .

Чтобы активировать эту функцию, выполните команду: shopt -s globstar.

Смотрите также: Как мне найти все файлы, содержащие определенный текст в Linux?

git grep

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

git grep "pattern"

что намного быстрее

ripgrep

Для более крупных проектов самый быстрый инструмент поиска - ripgrepэто рекурсивный поиск файлов по умолчанию:

rg "pattern" .

Он построен на основе движка регулярных выражений Rust, который использует конечные автоматы, SIMD и агрессивные буквальные оптимизации, чтобы сделать поиск очень быстрым. Проверьте подробный анализ здесь .


3
Спасибо за предложение git grep - это очень полезно, и я не знал об этом!
Бася

2
Спасибо за предложение ripgrep. Это намного быстрее.
Что было бы круто

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

11

просто имена файлов тоже могут быть полезны

grep -r -l "foo" .

10

Если вы хотите следовать только фактическим каталогам, а не символическим ссылкам,

grep -r "thingToBeFound" directory

Если вы хотите следовать символическим ссылкам, а также фактическим каталогам (будьте осторожны с бесконечной рекурсией),

grep -R "thing to be found" directory

Поскольку вы пытаетесь выполнить рекурсивный grep, вам также могут быть полезны следующие опции:

-H: outputs the filename with the line

-n: outputs the line number in the file

Поэтому, если вы хотите найти все файлы, содержащие Дарта Вейдера, в текущем каталоге или любых подкаталогах и захватить имя файла и номер строки, но не хотите, чтобы рекурсия следовала по символическим ссылкам, команда будет

grep -rnH "Darth Vader" .

Если вы хотите найти все упоминания слова cat в каталоге

/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
Проголосовал за то, что это единственное findрешение, которое позволяет избежать ненужного использования xargsи использования +вместо \;с -exec, тем самым избегая тонны ненужных запусков процессов. :-)
ShadowRanger

6

Это тот, который работал для моего случая на моей текущей машине (git bash на windows 7):

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

Я всегда забываю -print0 и -0 для путей с пробелами.

РЕДАКТИРОВАТЬ: мой предпочтительный инструмент теперь вместо ripgrep: https://github.com/BurntSushi/ripgrep/releases . Он действительно быстрый и имеет лучшие значения по умолчанию (например, рекурсивный по умолчанию). Тот же пример, что и мой оригинальный ответ, но с использованием ripgrep:rg -g "*.cs" "content pattern"


4

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

(^ credit: https://stackoverflow.com/a/1987928/1438029 )


Разъяснение:

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

grep -r "texthere" .(рекурсивно grep эти каталоги и подкаталоги)

grep рекурсивный

grep [options] PATTERN [FILE...]

[опции]

-R, -r, --recursive

Читать все файлы в каждом каталоге, рекурсивно.

Это эквивалентно опции -d recurseили --directories=recurse.

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

grep помогите

$ 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.


Скорость важна, если вам нужно делать это часто, но большинство из нас делают это только несколько раз в год. Установка новейшего стороннего инструмента juju du du jour является излишним, и решения, которые не сильно изменились с 1978 года, хорошо знать независимо от этого.
tripleee

Я считаю крайне неправдоподобным, что программист будет искать текст в дереве исходного кода только несколько раз в год. Но даже с точки зрения юзабилити, 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

Я использовал ripgrep, и это здорово. Но серебряный искатель фантастичен для программистов. +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" .

Возвращает все совпадения для текста здесь , начиная с корневого каталога, с соответствующим номером строки и игнорируя регистр:

grep -rni "texthere" /

флаги, используемые здесь:

  • -r рекурсивный
  • -n печатать номер строки с выводом
  • -i игнорировать регистр

1

Я думаю, это то, что вы пытаетесь написать

grep myText $(find .)

и это может быть что-то еще полезное, если вы хотите найти файлы grep hit

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

Это очень интуитивно понятно: например: grep -i acc $ (find. -Name "execute *. *")
Yu Shen

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В частности, это обходной путь для проблемы «Список аргументов слишком длинный».
tripleee

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

На какой платформе это будет? POSIXxargs стандартизирован, чтобы иметь такое поведение из коробки. « xargsУтилита должна ограничивать длину командной строки таким образом, чтобы при вызове командной строки комбинированные списки аргументов и среды ... не превышали {ARG_MAX} -2048 байтов».
трипл

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

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.