Tubería de un hallazgo a grep

8

¿Qué estoy tratando de hacer?

Escribir un comando que busque cualquier archivo que no sea requerido por ningún otro archivo en mi proyecto.

Que he probado

Estoy usando findpara obtener una lista de nombres de archivo. Ahora quiero usar los nombres de archivo como la cadena de búsqueda (en lugar del archivo para buscar).

Estoy usando find server/lib -type f -exec basename {} \; | cut -f 1 -d '.'para obtener mi lista de nombres de archivo y eliminar la extensión del archivo.

Ahora sé que esto grep -R --exclude-dir=node_modules <search-string> . -les a lo que quiero canalizar cada nombre de archivo, pero no sé cómo pasarlos como <search-string>argumento.


Otra información

También soy vagamente consciente de que canalizar esto greppodría pasar el resultado completo de find(la lista completa de archivos) que obviamente no quiero hacer si eso es lo que estoy a punto de hacer, entonces dígame.

Además, (aunque esto probablemente no esté en el alcance de esta pregunta), ya que estoy usando esto como una forma de encontrar cualquiera de los nombres de archivo que grepno pueden encontrar nada, cualquier consejo sobre cómo obtener este tipo de salida sería muy 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
fuente

Respuestas:

2

Respuesta corta:

Si solo quieres pasar un montón de líneas como argumentos a otro comando, xargses tu amigo, en este caso, porque lo estás poniendo en el medio de un comando, querrás usar la -I {}bandera. Esto se establece {}como un marcador de posición para que pueda colocarlo en cualquier lugar (puede establecer su propio marcador de posición, pero generalmente me mantengo, {}ya que no se confundirá con muchas otras cosas.

Poniendo todo junto (¡asumiendo que los comandos que has dado hacen lo que crees que hacen!):

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

Respuesta larga

Ok, entonces probablemente podamos llevar esto más lejos. Digamos que desea el formato que mencionó anteriormente, puede xargshacerlo sh -cpara poder encadenar comandos:

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

Al ejecutar esto en mi máquina, parece que esto le está dando los archivos donde se encuentra el archivo . Mi cerebro está cansado, así que en lugar de envolverlo en un lindo guión (que es lo que debes hacer cuando las líneas comienzan a volverse retorcidas, y usar https://www.shellcheck.net/ mientras estás en ello) puedes tenga este horrible truco en su lugar, que (creo) le dará la salida que está buscando:

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\""

Espiga
fuente
Muchas gracias, sí, xargs -I {}es lo que estaba buscando.
Simon Legg
6

Con zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/engrosamiento recursivo. Una característica introducida por zsha principios de los 90.
  • (D.:t:r)es un calificador global, una zshcaracterística específica que permite seleccionar archivos utilizando atributos distintos al nombre, o cambiar la clasificación o hacer modificaciones en los archivos encontrados.
  • D: incluye archivos de puntos y directorios de puntos de recorrido como lo findharía. Lo más probable es que quieras quitártelo.
  • .: solo archivos normales (como -type fen find)
  • :t, :r: modificadores del historial como en csh/ bashpero aquí se aplican a los archivos globales. :tpara la cola (nombre base), :rpara el nombre raíz (extensión eliminada).
  • x${^array}distribuye los elementos como lo harían rc's x^$arrayo fish' s x$array. Por ejemplo si $arrayes ( 1, 2). Eso se convierte x1 x2.
  • ${(u)array}(para unique), elimine los duplicados ( (u)siendo un indicador de expansión de parámetros).

Para la lista de archivos que no contienen ninguna de las cadenas, reemplace -lcon -L(suponiendo GNU grep, pero ya está usando opciones específicas de GNU aquí). -Fes para la búsqueda de cadenas fijas (ya que probablemente no desee que esos nombres de proyecto se traten como expresiones regulares). También es posible que desee agregar una -wopción greppara la coincidencia de palabras para que foo, foobarpor ejemplo , no coincida ( foo-baraunque sí lo haría ).

Stéphane Chazelas
fuente
Impresionantes gracias por esto y las explicaciones, no estaba al tanto de projects=(server/lib/**/*(D.:t:r))producir una matriz como esa en zsh. Sin embargo, ahora necesito enumerar los archivos donde grepno se pudo encontrar nada. ¿Supongo que necesitaría atrapar un código de salida 0 / falso?
Simon Legg
@ Simon, vea la parte -Lal final de la respuesta
Stéphane Chazelas
Si, lo ví. -lme dice dónde estaba el resultado de la búsqueda y -Ldónde no se encontró. Pero quiero saber una lista de los términos de búsqueda que no se encontraron en ningún lugar en lugar de donde se encontraron / no se encontraron
Simon Legg