Bash: existe uma maneira de procurar por uma string específica em um diretório de arquivos? [duplicado]

40

No bash, fiquei me perguntando se havia algum comando que informasse se uma string específica que você está procurando existe nos arquivos localizados no diretório atual em que você está.

Digamos que você esteja procurando pela 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 usando o vim e verificar a string 'toUpperCase' porque isso levaria muito tempo. Se não for uma linha de comando bash, existe outro método para fazer isso de forma eficiente?

    
por Dark Templar 10.10.2011 / 22:05

8 respostas

55

com grep :

grep -R "toUppercase()" *

Ou, se você tiver ack-grep instalado, simplesmente:

ack-grep "toUppercase"

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

ack-grep -cc "toUppercase()"

ack-grep também pode ser instalado no OSX, mas o executável é chamado apenas de ack .

    
por 10.10.2011 / 22:22
9

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

Para procurar a string toUpperCase( em todos os arquivos .c no diretório atual:

grep -F 'toUpperCase(' *.c

Se você quiser procurar em subdiretórios também:

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

Se você está procurando por chamadas de função C, então as ctags podem ser mais adequadas. 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 arquivo TAGS do ctags. Se você usa o Emacs, execute o programa semelhante etags .

    
por 10.10.2011 / 23:03
6

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

Previsivelmente, há sete respostas dizendo para usar grep . Mas eu pareço ser a única pessoa até agora que percebeu pela sua pergunta que você está usando vim . Como tal, embora você possa usar grep de dentro de vim , você pode também usar a ferramenta interna de vim . Isso é chamado por meio do comando :vimgrep .

Para pesquisar "todos os arquivos de origem C no diretório atual para chamadas à função toUpperCase() ", você digita o comando vim

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

A lista de correspondências resultante é automaticamente carregada na lista de correções rápidas, acessível com qualquer uma delas (veja a ajuda on-line para a diferença sutil)

:copen
:cwin

Para encontrar a função definição , em vez de chamá-la, ctags é a ferramenta, conforme mencionado em Gilles 'answer , em conjunto com os comandos :tjump ou :tselect .

Por que usar :vimgrep ?

A ajuda on-line ( :help grep ) enumera várias das razões, que não vou repetir aqui. Além disso, compare a ação de :vimgrep com a de dietbuddha 'answer . A linha de comando de dietbuddha bifurca um processo grep individual para cada arquivo de origem C individual. Ele nem emprega xargs para reduzir essa sobrecarga. E você ainda tem que, de alguma forma, analisar a saída para invocar seu editor de texto nos arquivos de origem relevantes assim que estiver terminado. :vimgrep não separa vários processos adicionais, e usar o resultado é a própria simplicidade. A simples seleção de uma das entradas na lista de correção rápida resultante posiciona automaticamente o cursor na linha relevante do arquivo de origem relevante.

Na verdade, ele faz exatamente o que você escreveu que você faria manualmente, exceto automaticamente. É a maneira automatizada de fazer essas mesmas ações do editor de texto. Ele carrega o arquivo como se carregado manualmente, procura por uma expressão regular (usando a sintaxe de expressão regular mesmo que você já está usando em vim ), registra os locais onde as correspondências ocorrem e depois descarrega o arquivo.

    
por 11.10.2011 / 13:32
3

Sim, a ferramenta é chamada grep .

The grep command searches one or more input files for lines containing a match to a specified pattern. By default, grep prints the matching lines.

O uso básico é:

grep something somewhere

Ou, mais especificamente:

grep [some options] pattern file

Em um caso muito simples, você deseja procurar recursivamente por todos os arquivos, portanto, você fornece a opção -r . Se você não se preocupa com letras maiúsculas ou minúsculas, insense a caixa com a opção -i .

grep -ri "touppercase()" .

Se você quiser apenas as partes correspondentes, use a opção -o .

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

    
por 10.10.2011 / 22:41
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 este é )

A 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 no link

    
por 10.10.2011 / 23:46
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ê quer, acho que o seguinte funciona bem. Eu tenho isso salvo como um script de shell e passar o valor que eu quero 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
    
por 10.10.2011 / 23:24
0

find e grep

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

por que não apenas grep ?

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

grep string *.c procura apenas os diretórios atuais .c files.

grep string **/*.c pesquisa todos os subdiretórios. No entanto, se você tiver um número muito grande de arquivos .c , correrá 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 começar o grep .

    
por 11.10.2011 / 06:33
0

Acho interessante que ninguém tenha respondido à sua pergunta específica: "como faço para encontrar se uma determinada string existe dentro dos arquivos localizados no diretório atual". Tanto quanto eu sei, não há opção grep que só retorna se uma correspondência foi encontrada em um grupo de arquivos. A opção mais próxima é -l para listar o (s) nome (s) de arquivo (s). A resposta mais próxima entre aqueles 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ê poderia tornar este script de shell mais genérico aceitando um segundo argumento para a extensão de arquivo sem muita dificuldade.

doug

    
por 11.10.2011 / 20:54

Tags