Questão Como usar o comando “grep” para encontrar texto incluindo subdiretórios


Eu quero encontrar todos os arquivos que contêm uma seqüência específica de texto. o grep comando funciona, mas eu não sei como usá-lo para cada diretório (eu só posso fazer isso para o meu diretório atual). Eu tentei ler man grep, mas não deu qualquer ajuda.


293
2017-08-01 11:38


origem


grep -RIn <yor pattern> * Irá procurar os diretórios atuais em todos os arquivos de texto. Não sei como fazer minha pesquisa recursivamente em padrões de arquivo como * .C com apenas grep
Curinga com --include="*.C" opção, @ user311346, graças a @Lekensteyn. - Bob Stein
Use a combinação find e grep para pesquisar recursivamente arquivos para uma cadeia de caracteres em todos os subdiretórios atuais e atuais. Verificar isso wilddiary.com/find-files-containing-my-text - Drona


Respostas:


Seria melhor usar

grep -rl "string" /path

Onde

  • -r (ou --recursive) é usada para percorrer também todos os subdiretórios /path, enquanto que
  • -l (ou --files-with-matches) opção é usada para imprimir apenas os nomes dos arquivos correspondentes, e não as linhas correspondentes (isso também pode melhorar a velocidade, dado que grep pare de ler um arquivo na primeira partida com essa opção).

376
2017-08-01 11:55



Na verdade, se "string" é um padrão de texto para encontrar, é melhor usar essa funcionalidade, caso contrário, alguém pode enfrentar problemas quando a string contém ponto ou caractere especial que tem significado em expressões regulares e não apenas um ponto que deve ser encontrado como string , como é. Então eu usaria -rlF comuta, -F para "string fixa" (e não regexp - por exemplo). Claro, se a tarefa estava usando regexps, então me desculpe. Claro, a mesma teoria sem -r também, muitas vezes vejo que as pessoas assumem pesquisas grep "texto" e pode causar problemas especiais que significam algo como um regexp. - LGB
Há também o -i bandeira que ignora o caso. - Marco Ceppi♦
Eu apenas mostraria o --recursive Opção, há uma tonelada de opções e cenários de uso que se pode falar. Comecei com a resposta aceita @dmityugov e modifiquei para trabalhar sem find. - enzotib
@ N.N .: feito :-) - enzotib
@ScottBiggs: com a opção --include '*.h' - enzotib


Se você está procurando por linhas correspondentes em arquivos, meu comando favorito é:

grep -Hrn 'search term' path/to/files
  • -H faz com que o nome do arquivo seja impresso (implícito quando vários arquivos são pesquisados)
  • -r faz uma pesquisa recursiva
  • -n faz com que o número da linha seja impresso

path/to/files pode ser . pesquisar no diretório atual

Outras opções que considero muito úteis:

  • -I ignorar arquivos binários (complemento: -a trate todos os arquivos como texto)
  • -F tratar search term como um literal, não uma expressão regular
  • -i faça uma pesquisa sem distinção entre maiúsculas e minúsculas
  • --color=always para forçar as cores, mesmo quando a tubulação less. Fazer less cores de suporte, você precisa usar o -r opção:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dir útil para excluir diretórios como .svn e .git.

Example output


138
2017-08-01 12:27



-H em uma pasta é redundante, se houver mais de um arquivo, como é provável. Na verdade, a página do homem diz -H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search. - enzotib
Eu não sabia disso, sempre funcionava como eu esperava. É o meu comando padrão ao procurar por arquivos. - Lekensteyn
Existe uma maneira de considerar apenas arquivos com uma extensão, digamos, .a (e combinar isso com -r)? - user2413
@ user2413 Experimente --include '*.*' - Lekensteyn
@enzotib Apenas um FYI: Eu não recebo a saída limpa de cada linha em todos os arquivos onde meu texto aparece com -rln nem -rl, mas eu faço com -Hrn. Redundante ou não, parece a imagem acima com as opções -Hrn. Além disso, não parece que -n funciona sem -H. - SgtPooki


Eu acredito que você pode usar algo assim:

find /path -type f -exec grep -l "string" {} \;

Explicação dos comentários

find é um comando que permite encontrar arquivos e outros objetos, como diretórios e links em subdiretórios de um determinado caminho. Se você não especificar uma máscara que os nomes de arquivos devem atender, ele enumera todos os objetos de diretório.

  • -type f especifica que ele deve processar apenas arquivos, não diretórios etc.
  • -exec grep especifica que para cada arquivo encontrado, ele deve executar o comando grep, passando seu nome de arquivo como um argumento para ele, substituindo {} com o nome do arquivo

21
2017-08-01 11:48



Só para quem não sabe, adicionando -name '*.py' restringe as correspondências aos arquivos terminados em '.py'. - Daniel F
Eu gosto que isso abrange clientes que não têm -R implementado em seu comando grep. - Aviose


Meu comando padrão é

grep -Rin string *

Eu uso um capitólio 'R' porque ls usa para recursivo. Já que o grep aceita ambos, não há razão para não usá-lo.

EDIT: por HVNSweeting, aparentemente -R seguirá links simbólicos onde, como -r não vou.


17
2017-08-01 14:43



Para pesquisar em arquivos ocultos também, execute shopt -s dotglob (lembrar -s de ativos"). Tenha cuidado ao remover arquivos. Se você tiver dotglob ativado, rm -r * remove tudo no diretório atual, mas Além dissoo diretório acima porque .. fósforos. Para desabilitar o dotglob, use shopt -u dotglob ("não definido"). As alterações são temporárias, mas só se aplicam ao shell atual. - Lekensteyn
Eu esqueci disso. Existe uma maneira de configurá-lo para uma linha? algo como shopt -s dotglob & <grep cmd> & shopt -y dotglob apenas mais conveniente? Dessa forma, não precisaremos nos preocupar com a redefinição - user606723
Além disso, é provavelmente mais fácil de usar grep -Rin string . na maioria desses casos. Eu só uso * porque parece vir mais naturalmente. - user606723
se você fizer grep recursivo, então você pode começar de "." ao invés de "*". nenhum dotglob necessário. - Michał Šrajer
vote acima disso, uma coisa que não menciona na manpage é R seguirá links simbólicos, r não - HVNSweeting


Se você está disposto a tentar algo novo, dê ack um tiro. O comando para pesquisar recursivamente o diretório atual para string é:

ack string

A instalação é bem simples:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Desde que você já tenha o diretório ~/bin e é preferencialmente no seu PATH.)


11
2017-08-01 15:09



Ou apenas apt-get install ack-grep (, e adicione alias ack = ack-grep ao seu .bashrc) - markijbema
O que os últimos parâmetros para o chmod comando fazer? Eles são específicos para chmod ou estão relacionados ao bash (o !#:3 parte)? - Elliott Darfink
@ElliottDarfink que está usando o Bash’s recurso de histórico - ! é um designador de evento. Eles são muito poderosos para evitar repetições. !#:3 faz referência ao terceiro token da linha de comando até o momento, ou seja, ~/bin/ack nesse caso. - Konrad Rudolph


O comando rgrep é dedicado para tal necessidade

Se não estiver disponível, você pode obtê-lo assim

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Você pode definir diretamente em suas opções grep padrão, conforme descrito acima.

Eu uso pessoal

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

tópico relacionado: como usar sempre o rgrep com cor


3
2018-01-02 13:58



O rgrep é fornecido pelo pacote grep, que é instalado por padrão no Ubuntu. - karel


Atualização 2:

Esta linha de comandos usando find e grep Corrige o problema:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> para saída colorida:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Exemplo:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Um exemplo executado no instantâneo abaixo: snap1


Atualização 1:

Você pode tentar seguir o código; como uma função em seu .bashrcou .bash_aliases ou em um script:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Uso: wherein /path/to/search/in/ searchkeyword

exemplo:

$ wherein ~/Documents/ "hello world"

(Nota: Como sugerido nos comentários abaixo por @enzotib, isto não funciona com arquivos / diretórios incluindo espaços em seus nomes.)


Postagem original

Para procurar a string e produzir apenas essa linha com a string de pesquisa:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

por exemplo.:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Para exibir o nome do arquivo que contém a string de pesquisa:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

por exemplo.:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

2
2018-01-25 11:11



Falha em nomes de arquivos contendo espaços. A falha é ocultada pelo fato de que stderr não é mostrado. - enzotib
@enzotib obrigado por apontar isso .. ainda não está resolvido para a função especificada .. Eu adicionei outro one-liner embora .. - precise
Agora a resposta é semelhante à de @dmityugov. - enzotib
sim, mas nesse sentido a maioria das respostas nesta página, se você verificar, são similares no que diz respeito a elas grep, ao lado disso sendo o subconjunto usando find com grep... mas se você aceitar interruptores e ajustes diferentes como uma resposta distinta, provavelmente o meu caberá aqui também ... ou você é diferente? a última atualização faz o que eu gostaria na minha pesquisa: nomes de arquivos com linhas com chave de busca e linha no. também :) e saída colorida e filtro de erro para melhor legibilidade .. - precise


Eu faço isso usando xargs, um comando muito subestimado

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

encontrar ./ ​​dá-lhe uma lista recursiva de todos os arquivos em uma pasta atual então você canaliza para xargs que executa o comando grep em cada um desses arquivos


1
2017-08-01 15:30



Usando xargs sem -print0 opção para find e -0 opção para xargs é reprovado, ele falhará em nomes de arquivos contendo espaços. - enzotib
@enzotib Eu editei a resposta como você sugeriu.- por favor revise e se precisar editar e corrigir, eu terei a re-edição feliz por você. obrigado - αғsнιη
@KasiyA: está tudo bem agora, removi meu downvote. - enzotib