Encontre arquivos recursivamente por conteúdo

Encontre arquivos recursivamente por conteúdo

Quero encontrar arquivos recursivamente em minha árvore de origem por conteúdo. Eu tentei o seguinte usando grep:

$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)

Isso me retorna todas as linhas que eu queria, mas agora gostaria de obter o nome de cada arquivo correspondente, então mudei para:

$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)

mas em vez de imprimir os nomes dos arquivos, só recebo

(standard input)

impresso em stdout. Como faço para corrigir isso para obter cada nome de arquivo e caminho (para usar sednele)?

O que eu quero fazer: Encontre todos os arquivos com printflinhas que também contenham %se bcm_errmsg(rv)aplique o seguinte comando sed aos arquivos encontrados:

sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'

Responder1

Acho que você está complicando demais as coisas. Para procurar string fooem todos os arquivos localizados no diretório e subdiretórios atuais, simplesmente execute

grep -r "foo" *

Por padrão, grep gera a linha correspondente anexada pelo nome do arquivo onde foi encontrado.

Em vez disso, o seguinte exibirá apenas o nome do arquivo, sem a linha correspondente:

grep -rl "foo" *

Responder2

Seguindo a ideia inicial do @steeldriver, você pode fazer:

egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'

Responder3

grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
        /%s/!b
        /printf/!b
        /bcm_errstr(rv)/!b
        s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'

Primeiro executamos um diretório recursivo. do diretório atual que procura arquivos que possuem as strings: printf, %s e bcm_errstr(rv) na mesma linha, mas talvez em qualquer ordem. As grepopções que nos ajudam a fazer isso são:

  • -r=> será iniciado recursivamente em todos os arquivos no diretório atual e abaixo.
  • -l=> listará os nomes de arquivos que correspondem aos critérios, ou seja, todas as 3 strings na mesma linha.
  • -Z=> os nomes de arquivos selecionados são separados por nulos (\0) em vez da nova linha usual (\n) para que possamos lidar com qualquer tipo de nome de arquivo.
  • -P=> habilitar o mecanismo regex Perl, por meio do qual podemos usar lookaheads para determinar se as 3 strings existem na mesma linha.

Do outro lado do pipe, xargsestá aguardando o recebimento dos nomes dos arquivos, separados por \0. Em seguida, ele alimenta todos esses nomes de arquivos, tanto quanto possível, para a linha de comando sed. O comando sed você já conhece da sua pergunta anterior, onde ele realiza as subs. somente nas linhas que contêm as 3 cordas na mesma linha.

informação relacionada