Estou procurando uma declaração de classe em um site com centenas de arquivos PHP. Como posso fazer isso na pasta atual e nas subpastas usando grep ?
Eu testei cd
ing para a pasta e, em seguida, algo como
grep -r 'class MyClass' *.php
Estou procurando uma declaração de classe em um site com centenas de arquivos PHP. Como posso fazer isso na pasta atual e nas subpastas usando grep ?
Eu testei cd
ing para a pasta e, em seguida, algo como
grep -r 'class MyClass' *.php
Respostas:
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"
Obviamente, isso pressupõe que você tenha apenas um espaço entre eles class
e o myClass
que pode não ser verdade. É fácil alterar o regexp para procurar qualquer número de espaços em branco.
Se você usar -r
, provavelmente desejará pesquisar recursivamente apenas o diretório atual :
grep -r 'class MyClass' .
Observe o período no final do acima.
O que você disse grep
foi que queria que ele pesquisasse recursivamente todos os *.php
arquivos ou diretórios , mas provavelmente não tinha nenhum diretório que terminasse em uma extensão .php. A descrição acima é a maneira mais simples possível 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 possui muitos outros tipos de arquivo, o acima é geralmente suficiente e funciona bem.
A maioria das encarnações do grep não tem como especificar extensões de arquivo que podem ser pesquisadas; portanto, 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 no GNU de find não suportam, então você pode usá-lo -name
.
A -exec
opção acima tem o efeito colateral de chamar grep para cada arquivo, o que é bastante caro.
Ainda outras versões do grep suportam um +
que diz ao find para anexar os argumentos juntos para reduzir o número de invocações do executável:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Uma maneira frequentemente recomendada de reduzir chamadas é usar xargs que dispararão o grep o menor número de vezes possível, mas quantas vezes for necessário:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
é inteligente o suficiente para transmitir grep até o número máximo de argumentos suportados na linha de comando, mas a variação acima não lida com certos caracteres como espaços muito bem. Por exemplo, se 'the file.php', um nome de arquivo grep receberia 'the' como argumento e 'file.php' como argumento para que ambos não fossem encontrados. Em vez disso, usamos:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
e -0
trabalhem juntos e usem argumentos seguidos por um caractere nulo para que o argumento seja identificado de maneira completa e inequívoca.
Se você tiver mais de um espaço depois class
ou uma guia, poderá permitir mais caracteres alterando a expressão regular:class[ \t]*MyClass
Esta postagem no StackOverflow tem outros exemplos e demonstra como excluir determinados diretórios, como os diretórios .svn.
Usando o sempre maravilhoso reconhecimento ,
ack --php 'class MyClass'
grep -r 'class MyClass' *.php
procurará em todas as pastas com nomes terminados em .php
grep -r 'class MyClass' . | grep .php
procurará a classe MyClass em todos os arquivos em todas as subpastas e retornará apenas os que tiverem .php.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
fornecerá o conteúdo da linha encontrada, bem como o caminho para o arquivo.
Provavelmente você deseja insensibilidade a maiúsculas e minúsculas, e o grep será encerrado 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 não produz um caminho inicial.
Se houver pelo menos um arquivo da extensão desejada, você poderá usar o egrep -ir. find
e xargs
mostre seu poder com diretórios simples (mas muito grandes) em que o grep falha e qualificadores extras (por exemplo, se você deseja procurar apenas arquivos .inc, .php e php3). Mas perde bastante conveniência e velocidade na minha experiência. Para declarações humanas de classe escrita, um grande problema será o espaço em branco. Então use egrep em vez de 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 pequenos relativamente 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 maneira:
egrep "pattern" *.[ip]*
Isso (com as primeiras opções) será bastante rápido e limitado principalmente aos arquivos php.
HTH
Eu sei que diz usando grep
, mas o meu favorito é usar ack-grep
:
ack-grep "class MyClass"
Isso é executado de forma recursiva, lista o nome do arquivo encontrado, com os números das linhas onde são encontrados e os 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; Definitivamente, eu o recomendaria (e navegaria em sua página de manual associada) para fazer coisas sofisticadas.
grep -r
não deu a você.