Como faço para grep recursivamente?


1682

Como recursivamente greptodos os diretórios e subdiretórios?

find . | xargs grep "texthere" *

110
@ TC1 O triste é que grep si pode responder à pergunta (pelo menos GNU grep): grep --help | recursiva grep
Frank Schmitt

7
Se você se encontra freqüentemente usando o grep para fazer pesquisas recursivas (especialmente se você faz muitas exceções de arquivos / diretórios manualmente), pode achar útil o ack (uma alternativa grep muito amigável para programadores).
Nick McCurdy

19
Na verdade, nem -r nem --recursive trabalho na caixa Solaris que uso no trabalho. E a página de manual do grep não menciona nada recursivo. Eu tive que recorrer para encontrar e me xargs.
Ben

8
ag é minha maneira favorita de fazer isso agora github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plnão funciona para mim no Redhat Linux. Eu recebo um erro "sem correspondência".
Bulrush

Respostas:


2507
grep -r "texthere" .

O primeiro parâmetro representa a expressão regular a ser pesquisada, enquanto o segundo representa o diretório que deve ser pesquisado. Nesse caso, .significa o diretório atual.

Nota: Isso funciona para o GNU grep e, em algumas plataformas como o Solaris, você deve usar especificamente o GNU grep em vez da implementação herdada. Para Solaris, este é o ggrepcomando.


39
Nota: "grep -r" funciona apenas em greps mais recentes. Não funciona no grep que acompanha, AIX 5.3por exemplo.
Retido

110
Use grep -R para seguir os links simbólicos.
Eloff

53
É bom saber que "-i" não diferencia maiúsculas de minúsculas e "-n" também inclui o número da linha para cada resultado correspondente.
Sadegh 23/01

24
Também é bom saber que, se você está procurando apenas uma sequência fixa e não uma expressão regular, use a opção -F. ele economizará muito tempo ao não chamar o analisador de expressões regulares. muito útil se você estiver pesquisando muitos arquivos.
6185 Jeff

6
alias rgrep = 'grep -r'
iniciado em 21/03

679

Se você conhece a extensão ou o padrão do arquivo que deseja, outro método é usar a --includeopção:

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

Você também pode mencionar arquivos para excluir --exclude.

Ag

Se você pesquisar com frequência o código, o Ag (The Silver Searcher) é uma alternativa muito mais rápida ao grep, personalizada para pesquisar o código. Por exemplo, é recursivo por padrão e ignora automaticamente os arquivos e diretórios listados .gitignore, para que você não precise continuar passando as mesmas opções de exclusão complicadas para grep ou find.


3
Funciona muito bem com o grep que vem com o Linux e Cygwin, mas não com o que vem com o AIX.
Retido

1
@KrzysztofWolny: `` em vez de =funcionar muito bem no Ubuntu. PS: esse é um espaço reservado, mas o analisador de remarcação SO falhou.
Dan Dascalescu

4
@DanDascalescu I upvoted para o grep, não para o Ag, só assim você sabe :)
Bernhard

1
Temos a opção de excluir um diretório enquanto pesquisamos recursivamente?
Tom Taylor

O cygwin do Windows gosta de aspas duplas--include "*.txt" --include "*.TXT"
Bob Stein

127

Além disso:

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

mas grep -ré uma resposta melhor.


14
Ou, se você não quiser se preocupar com espaços nos nomes de arquivos, find . -type f -exec grep "foo" '{}' \;funciona bem quando suportado.
Edd Steel

4
Se você deseja localizar através de xargs para grep, E se você estiver procurando apenas por uma sequência fixa (por exemplo, não uma regex), poderá se beneficiar de chamar a opção grep -F, para que o grep não carregue o mecanismo de regex para cada invocação. Se houver muitos arquivos, será muito mais rápido.
19413 Jeff

2
encontrar . -tipo f -exec grep -Hu "foo" {} \; é o que eu uso, pois fornece o nome do arquivo.
Wes

Isso funciona em todos os * nix porque é o POSIX 7
Ciro Santilli Enviado em 16/02/2014

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

118

Agora eu sempre uso (mesmo no Windows com GoW - Gnu no Windows ):

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

Isso inclui as seguintes opções:

--include=PATTERN

Recursar em diretórios apenas pesquisando a correspondência de arquivos PATTERN.

-n, --line-number

Prefixe cada linha de saída com o número da linha em seu arquivo de entrada.

(Nota: phuclv adiciona nos comentários que -ndiminuem muito o desempenho , portanto, você pode pular essa opção)

-R, -r, --recursive

Leia todos os arquivos em cada diretório, recursivamente; isso é equivalente à -d recurseopção.

-H, --with-filename

Imprima o nome do arquivo para cada correspondência.

-I     

Processe um arquivo binário como se não contivesse dados correspondentes;
isso é equivalente à --binary-files=without-matchopção.

E posso adicionar ' i' ( -nRHIi), se quiser resultados que não diferenciam maiúsculas de minúsculas.

Eu posso conseguir:

/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 parece promissor - mais recente que os utilitários GNU Windows que eu tenho usado. Tentando agora ...
Radim Cernej

qual é o significado do último caractere * aqui?
Lorniper

2
@lorniper faz com que o shell selecione todos os arquivos e pastas no diretório atual, fazendo com que o grep se aplique a esses arquivos e (recursivamente por causa da -Ropção) às pastas.
VonC 04/08/19

2
@ lorniper Noy exatamente: *ou .é um padrão glob (interpretado pelo shell): unix.stackexchange.com/a/64695/7490 . ' .' selecionará arquivos de pontos ou pastas de pontos (como .git/)
VonC 4/16

previamente Eu sempre usei grep -rnI, mas então eu aprendi que -ndiminui o desempenho muito , então eu só usá-lo quando realmente necessário e, normalmente, eu vou usar-rI
phuclv

25

Nos sistemas POSIX, você não encontra -rparâmetro para grepe grep -rn "stuff" .não será executado, mas se você usar o findcomando, ele irá:

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

Acordado por Solarise HP-UX.


qual é o significado de {} \; -print respectivamente?
user1169587

3
Em -execoption - symbol {}é uma referência ao nome do arquivo encontrado atualmente pela findferramenta (isto é, para fazer algo com o nome do arquivo que encontramos), também a -execopção deve ser encerrada com o ;símbolo (para marcar o final dos comandos exec), mas porque isso é tudo executando em um shell que símbolo deve ser escapado .. e finalmente a -printopção permite que a findferramenta imprima os nomes de arquivos encontrados na tela.
rook

19

globbing **

Usando grep -robras, mas pode exagerar, especialmente em pastas grandes.

Para uso mais prático, aqui está a sintaxe que usa a sintaxe de globbing ( **):

grep "texthere" **/*.txt

que recebe apenas arquivos específicos com o padrão selecionado. Ele funciona para shells suportados, como Bash +4 ou zsh .

Para ativar esse recurso, execute: shopt -s globstar.

Veja também: Como encontro todos os arquivos que contêm texto específico no Linux?

git grep

Para projetos sob controle de versão do Git, use:

git grep "pattern"

o que é muito mais rápido.

ripgrep

Para projetos maiores, a ferramenta de grepping mais rápida é a de ripgrepque greps arquivos recursivamente por padrão:

rg "pattern" .

Ele foi construído sobre o mecanismo de regex da Rust, que usa autômatos finitos, SIMD e otimizações literais agressivas para tornar a pesquisa muito rápida. Verifique a análise detalhada aqui .


3
Obrigado pela sugestão git grep - é muito útil e eu não sabia disso!
Basya

2
Obrigado pela sugestão do ripgrep. É muito mais rápido.
O que seria legal

11

Para encontrar o nome de filescom pathcontendo recursivamente o particular stringuso abaixo de comando para UNIX:

find . | xargs grep "searched-string"

para Linux:

grep -r "searched-string" .

encontre um arquivo no UNIXservidor

find . -type f -name file_name

encontre um arquivo no servidor LINUX

find . -name file_name

11

apenas os nomes de arquivos também podem ser úteis

grep -r -l "foo" .

10

Se você deseja apenas seguir diretórios reais, e não links simbólicos,

grep -r "thingToBeFound" directory

Se você deseja seguir os links simbólicos e os diretórios reais (tenha cuidado com a recursão infinita),

grep -R "thing to be found" directory

Como você está tentando grep recursivamente, as seguintes opções também podem ser úteis para você:

-H: outputs the filename with the line

-n: outputs the line number in the file

Portanto, se você deseja encontrar todos os arquivos que contêm Darth Vader no diretório atual ou em qualquer subdiretório e capturar o nome do arquivo e o número da linha, mas não deseja que a recursão siga os links simbólicos, o comando será

grep -rnH "Darth Vader" .

Se você quiser encontrar todas as menções à palavra gato no diretório

/home/adam/Desktop/TomAndJerry 

e você está atualmente no diretório

/home/adam/Desktop/WorldDominationPlot

e você deseja capturar o nome do arquivo, mas não o número da linha de qualquer instância da string "cats", e deseja que a recursão siga os links simbólicos, se os encontrar, você pode executar um dos seguintes

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

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

Fonte:

executando "grep --help"

Uma breve introdução aos links simbólicos, para qualquer pessoa que esteja lendo esta resposta e confusa com a minha referência a eles: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Ótima resposta. As opções extras (-rnh) são muito úteis, então obrigado por sugeri-las.
semtex41 8/03

8

ag é minha maneira favorita de fazer isso agora github.com/ggreer/the_silver_searcher . É basicamente a mesma coisa que ack, mas com mais algumas otimizações.

Aqui está uma pequena referência. Limpo o cache antes de cada teste (consulte /ubuntu/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

Se você estiver procurando por um conteúdo específico em todos os arquivos de uma estrutura de diretórios, poderá usar, findpois fica mais claro o que está fazendo:

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

Observe que -l(letras minúsculas de L) mostra o nome do arquivo que contém o texto. Remova-o se desejar imprimir a correspondência em si. Ou use -Hpara reunir o arquivo com a correspondência. No conjunto, outras alternativas são:

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

Onde -nimprime o número da linha.


2
Foi votada por ser a única findsolução para evitar o uso desnecessário xargse o uso em +vez de \;com ele -exec, evitando toneladas de lançamentos desnecessários de processos. :-)
ShadowRanger 30/01

6

Este é o que funcionou para o meu caso na minha máquina atual (git bash no windows 7):

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

Eu sempre esqueço o -print0 e -0 para caminhos com espaços.

EDIT: Agora minha ferramenta preferida é ripgrep: https://github.com/BurntSushi/ripgrep/releases . É muito rápido e tem melhores padrões (como recursivo por padrão). Mesmo exemplo da minha resposta original, mas usando ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (período de notificação no final)

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


Esclarecimento:

grep -r "texthere" /(grep recursivamente todos os diretórios e subdiretórios)

grep -r "texthere" .(grep recursivamente esses diretórios e subdiretórios)

grep recursivo

grep [options] PATTERN [FILE...]

[opções]

-R, -r, --recursive

Leia todos os arquivos em cada diretório, recursivamente.

Isso é equivalente à opção -d recurseou --directories=recurse.

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

grep help

$ grep --help

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

Alternativas

ack( http://beyondgrep.com/ )

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


4

Em 2018, você deseja usar ripgrepou the-silver-searcherporque eles são muito mais rápidos que as alternativas.

Aqui está um diretório com 336 subdiretórios de primeiro nível:

% 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

No OSX, este instala ripgrep: brew install ripgrep. Isso instala silver-searcher: brew install the_silver_searcher.


A velocidade é importante se você precisar fazer isso com frequência, mas a maioria de nós se vê fazendo isso apenas algumas vezes por ano, no máximo. A instalação da mais recente e divertida ferramenta de juju de terceiros é um exagero e é bom saber as soluções que não mudaram muito desde 1978.
Tripleee

Acho altamente implausível que um programador pesquise texto em uma árvore de origem apenas várias vezes por ano. Mas, mesmo do ponto de vista da usabilidade, rgtem uma vantagem considerável em juntar um comando grep recursivo do zero. Usando rg: rg foo. Usando ferramentas UNIX: find . | xargs grep foo. E se algum dos seus arquivos tiver uma citação, você precisará usá-lo find . -print0 | xargs -0 grep foo. Você vai se lembrar que se você usar isso algumas vezes por ano?
hughdbrown

1
Você está esquecendo o find . -type f -exec grep 'regex' {} +que é realmente fácil de lembrar se você usar essas ferramentas com alguma regularidade. Mas provavelmente você deve executar ctagsou etagsna sua árvore de origem de qualquer maneira, se precisar encontrar coisas com frequência.
tripleee

Eu tenho usado ripgrep e é ótimo. Mas o buscador de prata é fantástico para programadores. +1
Matt

3

No meu IBM AIX Server (versão do SO: AIX 5.2), use:

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

isso imprimirá o nome do caminho / arquivo e o número da linha relativa no arquivo, como:

./inc/xxxx_x.h

2865: / ** Descrição: stringYouWannaFind * /

de qualquer forma, funciona para mim :)


3

Abaixo está o comando para pesquisar um ambiente e Stringrecursivamente .UnixLinux

para UNIXcomando é:

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

para Linuxcomando é:

grep -r "string to be searched" .

2

Para uma lista de sinalizadores disponíveis:

grep --help 

Retorna todas as correspondências para o texto regexp no diretório atual, com o número da linha correspondente:

grep -rn "texthere" .

Retorna todas as correspondências para o texto aqui , começando no diretório raiz, com o número da linha correspondente e o caso de ignorância:

grep -rni "texthere" /

bandeiras usadas aqui:

  • -r recursivo
  • -n número da linha de impressão com saída
  • -i ignorar caso

1

Eu acho que é isso que você está tentando escrever

grep myText $(find .)

e isso pode ser outra coisa útil se você deseja encontrar os arquivos grep hit

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

É muito intuitivo: por exemplo: grep -i acc $ (encontre. -Nome "execução *. *")
Yu Shen

1

Jogando meus dois centavos aqui. Como outros já mencionaram, o grep -r não funciona em todas as plataformas. Isso pode parecer bobagem, mas eu sempre uso o git.

git grep "texthere"

Mesmo se o diretório não estiver preparado, eu apenas o preparo e uso o git grep.


0

Observe que find . -type f | xargs grep whatever tipos de soluções serão executados em erros de "lista de argumentos longos" quando houver muitos arquivos correspondidos por localização.

A melhor aposta é grep -rque, se isso não estiver disponível, use-o find . -type f -exec grep -H whatever {} \;.


Hã? xargsé especificamente uma solução alternativa para o problema "A lista de argumentos é muito longa".
Tripleee

2
Bem, no - xargs é especificamente para converter um conjunto de argumentos em um arglist, mas sim, é verdade que os xargs modernos, quando usados ​​com -s e / ou -L, podem lidar com arglists muito longos, quebrando várias invocações de comando, mas não está configurado dessa maneira por padrão (e não estava em nenhuma das respostas acima). Como exemplo:find . -type f | xargs -L 100 grep whatever
m.thome 23/04

Qual plataforma seria essa? O POSIXxargs é padronizado para ter esse comportamento pronto para uso. "O xargsutilitário limitará o comprimento da linha de comando de forma que, quando a linha de comando for chamada, as listas combinadas de argumentos e ambiente ... não excederão {ARG_MAX} -2048 bytes."
Tripleee

Hum. Embora os documentos do gnu sejam menos claros que o posix nessa base, e eu não tenha mais acesso à máquina que me levou a fazer essa afirmação, não posso confirmar minha interpretação original em nenhuma implementação atual. O grep recursivo é, é claro, ainda preferível, se disponível, mas há poucas razões para evitar a receita xargs (use -H para grep para evitar que a chamada final do grep passe apenas um único nome de arquivo).
precisa saber é o seguinte

0

Apenas por diversão, uma pesquisa rápida e suja de arquivos * .txt se a resposta @christangrant for demais para digitar :-)

grep -r texthere .|grep .txt


0

Aqui está uma função recursiva (testada levemente com bash e sh) que percorre todas as subpastas de uma determinada pasta ($ 1) e usa greppesquisas para uma determinada string ($ 3) em determinados arquivos ($ 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"

Executando-o e um exemplo de saída:

$ 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
Isso não acrescentar muito para outras respostas
Mel
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.