Você pode tentar
grep -r --include=*.php "search string" /path/to/dir
Eu estou procurando por uma declaração de classe em um site com centenas de arquivos PHP. Como posso fazer isso na pasta atual e nas subpastas usando o grep ?
Testei cd
ing para a pasta e, em seguida, algo como
grep -r 'class MyClass' *.php
Você pode tentar
grep -r --include=*.php "search string" /path/to/dir
Eu recomendo que você use algo como ctags em vez de fazê-lo com um grep. No entanto, se você quiser, pode fazer algo como
find <top level dir> -name \*.php | xargs grep "class MyClass"
Isso, obviamente, pressupõe que você tenha apenas um espaço entre class
e myClass
, o que pode não ser verdade. É fácil alterar o regexp para procurar qualquer número de espaços em branco.
Se você usa -r
, provavelmente deseja pesquisar recursivamente apenas o diretório atual :
grep -r 'class MyClass' .
Observe o período no final do acima.
O que você disse a grep
foi que você queria que ele pesquisasse recursivamente cada *.php
arquivo ou diretório , mas provavelmente você não tinha diretórios que tivessem terminado em uma extensão .php. A descrição acima é a maneira mais simples de fazer a pesquisa, mas também inclui arquivos de outros tipos, o que é especialmente problemático quando você tem diretórios .svn em todos os lugares. Se você não tem muitos outros tipos de arquivos, o acima é geralmente suficiente e funciona bem.
A maioria das encarnações do grep não tem como especificar extensões de arquivos que podem ser pesquisadas, então você geralmente usa o find em conjunto com ele:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
diz a algumas versões do grep que você deseja fazer uma pesquisa de nome de arquivo sem distinção entre maiúsculas e minúsculas, mas muitas das variantes não encontradas do GNU não o suportam, então você pode usar -name
.
A opção -exec
acima tem o efeito colateral de invocar o grep para cada arquivo, o que é bastante caro.
Ainda outras versões do grep suportam um +
que diz ao find para juntar os argumentos para reduzir o número de invocações do executável:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Uma maneira freqüentemente recomendada para reduzir invocações é usar xargs que dispararão o grep o menor número de vezes possível, mas quantas vezes forem necessárias:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
é inteligente o suficiente para passar o grep até o número máximo de argumentos suportados na linha de comando, mas a variação acima não manipula certos caracteres como espaços muito bem. Por exemplo, se 'filename.php', um nome de arquivo grep receberia 'the' como argumento e 'file.php' como argumento, então ambos não seriam encontrados. Em vez disso, usamos:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
e -0
trabalham juntos e usam argumentos seguidos por um caractere nulo para que o argumento seja completamente e sem ambigüidade identificado.
Se você tiver mais de um espaço após class
ou uma guia, convém permitir mais caracteres alterando a regex: class[ \t]*MyClass
Este post em O StackOverflow tem outros exemplos e demonstra como excluir determinados diretórios, como diretórios .svn.
Usando a sempre maravilhosa ack ,
ack --php 'class MyClass'
grep -r 'class MyClass' *.php
pesquisará todas as pastas cujos nomes terminem em .php
grep -r 'class MyClass' . | grep .php
irá procurar pela classe MyClass em todos os arquivos em todas as subpastas, então só retornará aqueles que possuem .php neles.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
fornecerá o conteúdo da linha e o caminho para o arquivo.
Caso os arquivos correspondentes possam ter nomes arbitrários, você deve considerar o uso de -print0
find . -type f -name '*.php' -print0 | xargs -0 grep 'class MyClass'
grep -rl 'class MyClass' . --include \*.php
l mostra apenas o nome do arquivo
r é recursivo
procura na pasta atual
- inclui limites de extensão de nome de arquivo
Provavelmente você quer tolerância a insensibilidade a maiúsculas e minúsculas e espaço em branco, e o grep terminará se não encontrar nenhuma instância do padrão de arquivo desejado no diretório atual. Ele precisa saber por onde começar, por assim dizer, e nenhum arquivo correspondente produz nenhum caminho inicial.
Se houver pelo menos um arquivo da extensão desejada, você poderá usar egrep -ir. find
e xargs
mostram seu poder com diretórios simples (mas muito grandes) que o grep falha e qualificadores extras (por exemplo, se você deseja procurar apenas por arquivos .inc, .php e php3). Mas perde um pouco de conveniência e velocidade na minha experiência. Para declarações de classes escritas por humanos, um grande problema será o espaço em branco. Então use o egrep ao invés do grep. Também LC_ALL = C para velocidade extra. Por conveniência, costumo usar:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
Isso ainda pode corresponder a comentários, como // class myclass exists in file
, mas acho que eles são relativamente pequenos e podem ser filtrados com ... | fgrep -v '//'
Você também pode incluir máscaras de arquivo mais complexas (por exemplo, para capturar a maioria dos arquivos .inc e .php) no padrão do arquivo egrep da seguinte forma:
egrep "pattern" *.[ip]*
Isso (com as primeiras opções) será bastante rápido e limitado a arquivos php.
HTH
Eu sei que usa grep
, mas meu favorito é usar ack-grep
:
ack-grep "class MyClass"
Isso é executado recursivamente, lista o nome do arquivo em que encontra resultados, com números de linha para onde eles são encontrados e destaques. Para direcionar especificamente arquivos php, você pode executar:
ack-grep --type-set php:ext:php "path"
O pacote tem uma infinidade de opções; Eu definitivamente recomendo (e navega em sua página de manual associada) por fazer coisas extravagantes.