Canalizando de uma descoberta para o grep

8

O que estou tentando fazer?

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

O que eu tentei?

Estou usando findpara obter uma lista de nomes de arquivos. Agora eu quero usar os nomes de arquivo como a string de pesquisa (em vez do arquivo a ser pesquisado).

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


Outras informações

Também estou vagamente ciente de que a canalização para isso greppode passar o resultado inteiro do find(toda a lista de arquivos) que obviamente não quero fazer, se é isso que estou prestes a fazer, então me diga.

Além disso, (embora isso provavelmente não esteja no escopo desta pergunta), como eu estou usando isso como uma maneira de encontrar qualquer um dos nomes de arquivos que grepnão conseguem encontrar nada, qualquer conselho sobre como obter esse tipo de saída seria muito apreciado

> <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)
Simon Legg
fonte

Respostas:

2

Resposta curta:

Se você apenas deseja passar um monte de linhas como argumentos para outro comando, xargsé seu amigo - nesse caso, porque você o coloca no meio de um comando, você deve usar a -I {}flag. Isso é definido {}como um espaço reservado para que você possa colocar em qualquer lugar (você pode definir seu próprio espaço reservado, mas eu normalmente continuo, {}pois não será confundido com muitas outras coisas.

Juntando tudo (assumindo que os comandos que você deu fazem o que você pensa 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. Vamos dizer que você queria o formato que você mencionou anteriormente - que puder xargspara sh -cque você possa comandos cadeia:

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

Ao executar isso na minha máquina, parece que isso está fornecendo os arquivos onde o arquivo foi encontrado. Meu cérebro está cansado, então, em vez de envolvê-lo em um bom roteiro (que é o que você realmente deve fazer quando os oneliners começarem a ficar feios e usar https://www.shellcheck.net/ enquanto estiver fazendo isso), você pode tenha esse hack horrível, o que (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\""

Espinho
fonte
Muito obrigado, sim, xargs -I {}é o que eu estava procurando.
Simon Legg
6

Com zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/globbing recursivo. Um recurso introduzido zshno início dos anos 90.
  • (D.:t:r)é um qualificador global, um zshrecurso específico que permite selecionar arquivos usando atributos diferentes de nome ou alterar a classificação ou fazer modificações nos arquivos encontrados.
  • D: inclua arquivos de ponto e dirija pontos-dirs como findfaria. Provavelmente, você gostaria de tirar isso.
  • .: apenas arquivos regulares (como -type fem find)
  • :t, :r: modificadores de histórico como em csh/ bashmas aqui aplicados aos arquivos globbed. :tpara a cauda (nome da base), :rpara o nome da raiz (extensão removida).
  • x${^array}distribui os elementos como rc's x^$arrayou fish' s x$arrayfaria. Por exemplo, se $arrayfor ( 1, 2). Isso se torna x1 x2.
  • ${(u)array}(por exemplo u), remova duplicatas ( (u)sendo um sinalizador de expansão de parâmetro).

Para a lista de arquivos que não contêm nenhuma das strings, substitua -lpor -L(assumindo o GNU grep, mas você já está usando opções específicas do GNU aqui). -Fé para pesquisa de string fixa (como você provavelmente não deseja que esses nomes de projetos sejam tratados como regexps). Você também pode querer ativar uma -wopção greppara correspondência de palavras , para que foonão corresponda, foobarpor exemplo (ainda assim corresponderia foo-bar).

Stéphane Chazelas
fonte
Agradecimentos impressionantes por isso e pelas explicações, eu não estava ciente da projects=(server/lib/**/*(D.:t:r))produção de uma matriz como essa no zsh. No entanto, agora preciso listar os arquivos onde grepnão foi possível encontrar nada. Eu acho que precisaria pegar um código de saída 0 / falso?
precisa
@Simon, consulte a parte sobre -Lno final da resposta
Stéphane Chazelas
Sim, eu vi aquilo. -linforma onde está o resultado da pesquisa e -Lindica onde não foi encontrado. Mas eu quero saber uma lista das buscas-termos que não foram encontrados em qualquer lugar, em vez de onde eles foram / não foram encontrados
Simon Legg