Encontrando uma subcadeia de arquivos nos subdiretórios com um único comando interno?


10

No Windows, se eu quisesse encontrar uma string em todos os arquivos em todos os subdiretórios, faria algo como

findstr /C:"the string" /S *.h

No entanto, no Linux (por exemplo, Ubuntu) eu encontrei nenhuma outra maneira do que alguns comando direcionado envolvendo find, xargse grep(um exemplo é a esta página: ? Como posso recursivamente grep através de sub-diretórios ). No entanto, minha pergunta é diferente: existe algum comando interno que funcione com essa mágica, sem ter que escrever meu shell script?

Respostas:


19

O GNU grep permite pesquisar recursivamente através de subdiretórios:

grep -r --include='*.h' 'the string' .

Eu tentei esta linha de comando exata no Ubuntu, mas obter "grep: opção inválida - 'M'", embora eu não posso ver qualquer 'M' em qualquer lugar ... intrigante
Guido Domenici

@Guido Funciona bem aqui
phunehehe

Em uma edição sugerida, o TomasG recomenda alterar o último *para '*': "É necessário citar o último curinga para evitar erros quando algum nome de arquivo começa com -"
Michael Mrozek

Em uma estranha reviravolta dos eventos, agora também funciona para mim, conforme inserido na resposta original. Obrigado!
Guido Domenici

1
@Guido: Seu problema pode ter sido devido a um arquivo no diretório atual chamado -Msomethingou a uma GREP_OPTIONSconfiguração.
Gilles 'SO- stop be evil'

2

grep -r searchpattern /path/to/start/in

Onde /path/to/start/in/pode ser apenas " ." para o diretório atual.


1

Não. find -name \*.h -print0 | xargs -0 grep -l 'the regex'É tão mágico quanto ele ganha.


O GNU grep possui os casos comuns integrados com sua -ropção. Não há necessidade da artilharia pesada.
Gilles 'SO- stop be evil'

3
xargsadiciona apenas ruído. Usofind -name \*.h -execdir grep -l 'the regex {} +
usuário desconhecido

0

existe algum comando interno que funcione com essa mágica ...?

Para ser pedante, não, você não pode assumir que esse comando existe .

Existem muitas implementações diferentes do Unix, e cada uma tem suas peculiaridades diferentes. POSIX, o denominador comum (e a coisa mais próxima de um padrão nos Unices) não especifica essa opção paragrep .

Como mencionado em outras respostas, a implementação do GNU greppossui uma opção não padrão que faz o que você deseja. Embora essa implementação específica possa ser comum em sistemas Linux, você não pode assumir sua disponibilidade em nenhum Unix, mesmo em alguns sistemas Linux.

Por fim, devo mencionar que é a filosofia do Unix favorecer a combinação de vários programas primitivos, sobre o uso de um grande executável monolítico tentando fazer tudo de uma vez.

No seu caso, rastrear o sistema de arquivos e regexp correspondente em um fluxo são duas tarefas separadas. É normal tratar cada um em um programa separado.


0

Para encontrar a string do diretório especificado, use o comando abaixo

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Por exemplo:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;

1
greppode usar mais de um arquivo como argumento; portanto, você deve usá-lo em +vez de \;evitar executar uma grepchamada por arquivo, o que é bastante ineficiente.
Stéphane Chazelas

1
Observe que se -name '*'restringe a arquivos cujo nome é texto válido no código do idioma atual ( findpelo menos em algumas implementações), mas os outros componentes de diretório ainda podem conter seqüências de bytes que não formam caracteres válidos. Se sua intenção -name '*'era garantir que a saída fosse um texto válido (omitindo os arquivos com nomes impróprios), você preferiria usar find ... ! -name '*' -prune -o -exec grep ... {} +, o que também impediria findde descer para diretórios com nomes impróprios.
Stéphane Chazelas
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.