Piping de um achado no grep

8

O que estou tentando fazer?

Escreva um comando que procure por arquivos que não estejam sendo exigidos por nenhum outro arquivo no meu projeto.

O que eu tentei?

Estou usando find para obter uma lista de nomes de arquivos. Agora quero usar os nomes dos arquivos como a string de pesquisa (em vez do arquivo a pesquisar).

Estou usando find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' para obter minha lista de nomes de arquivos e remover a extensão do arquivo.

Agora eu sei que este grep -R --exclude-dir=node_modules <search-string> . -l é o que eu quero canalizar cada nome de arquivo, mas não sei como passá-los como o argumento <search-string> .

Outras informações

Eu também estou vagamente ciente de que o encanamento para este grep pode passar todo o resultado do find (a lista inteira de arquivos) que eu obviamente não quero fazer se é isso que eu sou prestes a fazer, então me diga.

Além disso, (embora isso provavelmente não esteja no escopo desta questão), já que estou usando isso como uma forma de encontrar qualquer um dos nomes de arquivos para os quais grep não consegue encontrar nada, qualquer conselho sobre como obter esse tipo de saída seria muito apreciada

> <the-command>

filename1
server/lib/foo.js # where these are the list of files in which it appears
test/lib/foo.js

filename2
Not Found! #where 'filename2' wasn't found anywhere (obviously)
    
por Simon Legg 26.03.2017 / 21:30

2 respostas

2

Resposta curta:

Se você quer apenas passar um monte de linhas como argumentos para outro comando, xargs é seu amigo - neste caso, porque você está colocando-o no meio de um comando, você vai querer usar o comando -I {} flag. Isso define {} como um espaço reservado para que você possa colocá-lo em qualquer lugar (você pode definir seu próprio espaço reservado, mas eu costumo ficar com {} , pois não será confundido com muitas outras coisas.

Juntando tudo (assumindo que os comandos que você deu façam o que você acha que eles fazem!):

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} grep -R --exclude-dir=node_modules {} . -l

Resposta longa

Ok, então provavelmente podemos levar isso adiante. Digamos que você queria o formato mencionado anteriormente - você pode xargs to sh -c para poder comandar a cadeia:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l"

Rodando isso na minha máquina, parece que isso está te dando os arquivos onde o arquivo é encontrado. Meu cérebro está cansado, então, em vez de envolvê-lo em um script legal (que é o que você deve fazer quando os oneliners começam a ficar retorcidos, e use link enquanto você está nisso) você pode ter este hack horrível em seu lugar, que (eu acho) lhe dará a saída que você está procurando:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l && printf \"\n\" || printf \"Not found\n\n\""

    
por 27.03.2017 / 23:17
6

com zsh :

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/ globalização recursiva. Um recurso introduzido por zsh no início dos anos 90.
  • (D.:t:r) é um qualificador glob, um recurso zsh -specific que permite selecionar arquivos usando atributos diferentes de name, ou alterar a ordenação ou fazer modificações nos arquivos encontrados.
  • D : inclui arquivos de ponto e atravessam dot-dirs como find . O mais provável é que você queira tirar essa.
  • . : somente arquivos regulares (como -type f in find )
  • :t , :r : modificadores de histórico como em csh / bash , mas aqui aplicados aos arquivos globbed. :t para o final (nome da base), :r para o nome da raiz (extensão removida).
  • x${^array} distribui os elementos como rc ' x^$array ou fish ' x$array faria. Por exemplo, se $array for ( 1 , 2 ). Isso se torna x1 x2 .
  • ${(u)array} (para u nique), remova duplicatas ( (u) sendo um sinalizador de expansão de parâmetro).

Para a lista de arquivos que contêm none das strings, substitua -l por -L (assumindo o GNU grep , mas você já está usando as opções específicas do GNU aqui). -F é para pesquisa de cadeia fixa (como você provavelmente não deseja que esses nomes de projeto sejam tratados como expressões regulares). Você também pode adicionar uma opção -w à correspondência de grep para palavra para que foo não corresponda em foobar , por exemplo (ainda corresponderia a foo-bar ).

    
por 26.03.2017 / 21:48