Bash: existe uma maneira de procurar uma determinada string em um diretório de arquivos? [duplicado]

47

Possível duplicado:
pesquise um padrão de texto no linux

No bash, eu queria saber se havia algum comando que o informasse se uma determinada string que você está procurando existe nos arquivos localizados no diretório atual em que você está.

Digamos que você esteja procurando a função 'toUpperCase ()' dentro de um conjunto de arquivos C em seu diretório atual. Existem muitos arquivos, então você não gostaria de abrir manualmente cada um deles usando o vim e verificar a string 'toUpperCase' porque isso levaria muito tempo. Se não for uma linha de comando do bash, existe outro método para fazer isso com eficiência?

Templário Sombrio
fonte

Respostas:

64

Com grep:

grep -R "toUppercase()" *

Ou, se você tiver o ack-grep instalado, basta:

ack-grep "toUppercase"

Se você deseja limitar a pesquisa em arquivos C, com ack-grep:

ack-grep -cc "toUppercase()"

ack-greptambém pode ser instalado no OSX, mas o executável é chamado just ack.

Trasplazio Garzuglio
fonte
Tanto é assim que SO já tem um desconfiado pergunta semelhante ;)
David Perry
10

A ferramenta de pesquisa de texto padrão é grep .

Para procurar a sequência toUpperCase(em todos os .carquivos no diretório atual:

grep -F 'toUpperCase(' *.c

Se você deseja procurar também nos subdiretórios:

grep -r --include='*.c' -F 'toUpperCase('

Se você estiver procurando por chamadas de função C, as ctags podem ser melhores. Você o executa uma vez em todos os seus arquivos de origem para criar um índice de identificadores e, em seguida, usa seu editor para navegar entre as chamadas. Todos os editores do tipo vi podem usar o TAGSarquivo ctags . Se você usa o Emacs, execute o programa semelhante etags.

Gilles 'SO- parar de ser mau'
fonte
ctagsé útil para encontrar definições de função , não chamadas de função .
JdeBP #
6

Você está usando o vim. Você tem uma ferramenta para fazer isso embutido.

Previsivelmente, já existem sete respostas dizendo para usar grep. Mas pareço ser a única pessoa até agora que notou da sua pergunta que você está usando vim. Como tal, embora você possa usar grepde dentro vim, você também pode usar vima ferramenta interna . Isso é chamado através do :vimgrepcomando

Para pesquisar "todos os arquivos de origem C no diretório atual para chamadas para a função toUpperCase()", digite o vimcomando

:vimgrep "\<toUpperCase\_s*(" *.c

A lista de correspondências resultante é carregada automaticamente na lista de correções rápidas, acessível por qualquer um dos dois (consulte a ajuda on-line para saber a diferença sutil)

:copen
:cwin

Encontrar a definição da função , em vez de chamá-la, ctagsé a ferramenta, conforme mencionado na Gillesresposta de , em conjunto com os comandos :tjumpou :tselect.

Por que usar :vimgrep?

A ajuda on-line ( :help grep) enumera vários dos motivos, que não serão exibidos aqui. Além disso, compare a ação :vimgrepcom a da dietbuddharesposta . dietbuddhaA linha de comando do bifurca um grepprocesso individual para cada arquivo de origem C. Nem sequer é empregado xargspara reduzir essa sobrecarga. E você ainda precisa analisar de alguma forma a saída para chamar seu editor de texto nos arquivos de origem relevantes, uma vez finalizado. :vimgrepnão realiza múltiplos processos adicionais, e usar o resultado é a própria simplicidade. Simplesmente selecionar uma das entradas na lista de correções resultantes resultante automaticamente posiciona o cursor na linha relevante do arquivo de origem relevante.

De fato, ele faz exatamente o que você escreveu à mão, exceto automaticamente. É a maneira automatizada de executar essas ações do editor de texto. Ele carrega o arquivo como se fosse carregado manualmente, procura uma expressão regular (usando a mesma sintaxe de expressão regular que você já está usando em outros lugares vim), registra os locais onde as correspondências ocorrem e, em seguida, descarrega o arquivo.

JdeBP
fonte
2

Sim, a ferramenta é chamada grep.

O comando grep procura em um ou mais arquivos de entrada por linhas contendo uma correspondência com um padrão especificado. Por padrão, grep imprime as linhas correspondentes.

O uso básico é:

grep something somewhere

Ou, mais especificamente:

grep [some options] pattern file

Em um caso muito simples, você deseja recursivamente pesquisar todos os arquivos, fornecendo a -ropção. Se você não se importa com maiúsculas ou minúsculas, faça distinção entre maiúsculas e minúsculas com a -iopção

grep -ri "touppercase()" .

Se você deseja apenas as partes correspondentes, use a -oopção

O Grep pode usar expressões regulares e possui um manual enorme .

slhck
fonte
2

grepé a resposta padrão - usando o sinalizador -r para pesquisar recursivamente ou em conjunto com find(discussão e exemplos em outras perguntas neste site, como esta )

Minha escolha preferida ultimamente é ack. Não é provável que esteja instalado no seu computador, mas você pode instalar usando o apt-get no Ubuntu ou simplesmente fazer o download. Links, instruções e razões pelas quais é melhor que o grep estão disponíveis em http://betterthangrep.com/

Doug Harris
fonte
1

find e grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

por que não somente grep?

grep -r string .irá recursar através de todos os arquivos no diretório atual. Se você tiver arquivos de objeto ou outros binários, poderá obter uma correspondência com os resultados binários também conhecidos como. lixo. Se também houver arquivos de dispositivo ou fifos em seu subdiretório, você poderá ter consequências desconhecidas / não intencionais.

grep string *.cpesquisa apenas os .carquivos de diretórios atuais .

grep string **/*.c pesquisa todos os subdiretórios. No entanto, se você tiver um número muito grande de .carquivos, corre o risco de exceder o número máximo de expansões para o shell glob. A expansão também tem que acontecer primeiro, o que significa uma travessia completa da árvore antes de grepcomeçar.

dietbuddha
fonte
0

O Grep fará o truque, mas um pouco de script adicional ajudará a encontrar o nome do arquivo e a linha exata referenciada. Se é isso que você deseja, acho que o seguinte funciona bem. Eu o salvei como um script de shell e transmito o valor que desejo como primeira opção de linha de comando.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
Tim Brigham
fonte
3
O grep possui uma opção -H, que já faz isso. grep -Hn o que quer *
Roy Rico
Aprenda algo novo todos os dias .. Obrigado @Roy Rico
Tim Brigham
0

Acho interessante que ninguém tenha respondido à sua pergunta específica: "como faço para descobrir se existe uma string específica nos arquivos localizados no diretório atual". Até onde eu sei, não há opção grep que retorne apenas se uma correspondência foi encontrada em um grupo de arquivos. A opção mais próxima é -l para listar os nomes dos arquivos. A resposta mais próxima entre as pessoas até agora é de tim, com alguns pequenos ajustes:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

Você pode tornar esse script de shell mais genérico aceitando um segundo argumento para a extensão do arquivo sem muitos problemas.

doug

SnoopDougieDoug
fonte