Exibir nome do arquivo antes da linha correspondente

282

Como posso grepexibir o nome do arquivo antes das linhas correspondentes em sua saída?

Vivek
fonte
2
pls contar a sua versão grepgrep --version
Kent
3
kent, grep --versionesse é o comando a ser usado para conhecer a versão grep? Se assim for, não está funcionando. Não foi possível encontrar nenhum outro comando para conhecer a versão grep.
Vivek
2
boa pergunta, mas 'Versão do sistema
operacional
1
O SO e a versão são irrelevantes aqui.
MD XF
grep 'pattern' *
User0

Respostas:

430

Experimente este pequeno truque para persuadir grep -se de que está lidando com vários arquivos, para exibir o nome do arquivo:

grep 'pattern' file /dev/null

Para também obter o número da linha:

grep -n 'pattern' file /dev/null
Scrutinizer
fonte
6
Sim, funcionou. Você pode me dizer qual é o significado de adicionar /dev/nulleste comando?
Vivek
55
Se grepfor fornecido com vários nomes de arquivos, ele os exibirá automaticamente antes da partida, mas deixará o nome do arquivo no caso de um único arquivo de entrada. Ao usar /dev/nullcomo um arquivo de entrada extra grep"pensa" que lidar com vários arquivos, mas / dev / null é, naturalmente, esvaziar, por isso não vai aparecer na lista jogo ..
Scrutinizer
32
Usar / dev / null é um truque inteligente, mas acho que a sugestão abaixo da bandeira -H é uma resposta melhor.
JohnQ
22
OK, mas a -Hopção para grep não faz parte do POSIX, e o sistema operacional usado é o Solaris 10, onde nem o grep padrão nem a versão compatível com POSIX do grep têm a -Hopção.
Escrutinador
4
Isso é importante se você estiver usando grep com find, como find . -name foo -exec grep pattern {} \;- assumindo muitos arquivos nomeados fooem seu subdiretório, findainda entregará grepum único arquivo para operar por vez. O /dev/nulltruque parece funcionar em todos os sabores linux / osx que eu tentei, então parabéns! Note que acho que -Hé mais limpo, mas, como mencionado abaixo, pode não ser compatível com a sua versão do grep.
V Jon
296

Se você tem as opções -H e está -ndisponível ( man grepé seu amigo):

$ cat file
foo
bar
foobar

$ grep -H foo file
file:foo
file:foobar

$ grep -Hn foo file
file:1:foo
file:3:foobar

Opções:

-H, --com o nome do arquivo

Imprima o nome do arquivo para cada correspondência. Esse é o padrão quando há mais de um arquivo para pesquisar.

-n, --line-number

Prefixe cada linha de saída com o número da linha com base em 1 em seu arquivo de entrada. (-n é especificado pelo POSIX.)

-Hé uma extensão GNU, mas -né especificada pelo POSIX

Chris Seymour
fonte
3
Não, -Hnão é suportado aqui.
Vivek
1
Suportado, mas sempre dá grep: file: Nenhum tal lima ou diretório
pal4life
2
funciona no ubuntu -H e -n. Provavelmente com todas as versões mais recentes de * nix
tgkprog
1
Eu lutei com isso por anos sem noite pensando que havia essas opções!
GreenSaguaro
45

Não é necessário truque.

grep --with-filename 'pattern' file

Com números de linha:

grep -n --with-filename 'pattern' file
MD XF
fonte
3
@ codeforester Eu não conheço nenhum outro greps, então eu não sei.
MD XF
2
Legal ! isso funcionou para linux. se você usa mac, pode instalar o coreutils com o brew. E lembre-se add PATH = "/ usr / local / opt / coreutils / libexec / gnubin: $ PATH" ao seu .bashrc
zw963
2
Isso (também) funcionou no MinGW (1.0.17, eu acho).
31516 Peter Mortensen
Funciona para mim com o Mac grep embutido (2.5.1-FreeBSD). Mas, para usar o grep alternativo do Homebrew, outra maneira é executar brew install grepe usar ggrep. Não há necessidade de modificar PATH.
wonderlr
5

Que tal isso, que consegui graças, em parte, a este post.

Você deseja encontrar vários arquivos, digamos logs com nomes diferentes, mas com um padrão (por exemplo filename=logfile.DATE), dentro de vários diretórios com um padrão (por exemplo /logsapp1, /logsapp2). Cada arquivo tem um padrão que você deseja grep (por exemplo "init time") e deseja ter o "init time"de cada arquivo, mas sabendo a qual arquivo pertence.

find ./logsapp* -name logfile* | xargs -I{} grep "init time" {} \dev\null | tee outputfilename.txt

Então, outputfilename.txtseria algo como

./logsapp1/logfile.22102015: init time: 10ms
./logsapp1/logfile.21102015: init time: 15ms
./logsapp2/logfile.21102015: init time: 17ms
./logsapp2/logfile.22102015: init time: 11ms

Em geral

find ./path_pattern/to_files* -name filename_pattern* | xargs -I{} grep "grep_pattern" {} \dev\null | tee outfilename.txt

Explicação:

find O comando pesquisará os nomes de arquivos com base no padrão

então, o pipe xargs -I{}redirecionará a findsaída para o{}

qual será a entrada para grep ""pattern" {}

Em seguida, o truque para grepexibir os nomes dos arquivos\dev\null

e, finalmente, escreva a saída em arquivo com tee outputfile.txt

Isso funcionou para mim na grepversão 9.0.5 build 1989.

Lejuanjowski
fonte
3
Ou apenas usando findfind ./path_pattern/to_files -type f -name "files*.log" -exec grep -Hn pattern {} \;
Martin
1

Esta é uma pequena modificação de uma solução anterior. Meu exemplo procura o redirecionamento stderr nos scripts bash: grep '2>' $(find . -name "*.bash")

Richard Jessop
fonte
-7
grep 'search this' *.txt

trabalhou para eu pesquisar todos os arquivos .txt (insira seu próprio valor de pesquisa, é claro).

MagicMojo
fonte