¿Cómo puedo obtener los resultados de ENCONTRAR usando -EXEC y aún enviar a un archivo?

64

Mejor explicar en ejemplos.

Yo puedo:

find . -name "*.py" -type f > output.txt

Pero, ¿cómo puedo almacenar la salida en el mismo archivo para:

find . -name "*.py" -type f -exec grep "something" {} \

No puedo simplemente hacer

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
bakytn
fuente

Respuestas:

106

Si te entiendo correctamente, esto es lo que quieres hacer:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Findtodos los archivos con extensión py, grepsolo las filas que contienen somethingy guardan las filas output.txt. Si el archivo contiene algo, será reemplazado.

Editar: Usando -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

Estoy incorporando el comentario de Chris Downs aquí. El comando anterior dará como resultado que grepse ejecute tantas veces como findencuentre ocurrencias. Sin embargo, si reemplaza el ;con a +, grepse llama con la salida de findconcatenado (hasta cierto límite). Vea la pregunta Usando punto y coma (;) vs plus (+) con exec en find para más información sobre el tema.

johnny
fuente
16
Usar en +lugar de \;mejorará significativamente el tiempo de ejecución (ya que contaminará los argumentos antes de la ejecución hasta ARG_MAX).
Chris Down
¡Ahora entiendo el poder de los xargs! ¡Gracias!
domih
55
Úselo grep -Hsi desea incluir el nombre de archivo del archivo en la salida.
Steinar
18

Si desea guardar todas las líneas coincidentes en todos los archivos output.txt, su último comando funciona, excepto que le falta el requerido ;al final del comando.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

Si desea que cada ejecución de grepproduzca resultados en un archivo diferente, ejecute un shell para calcular el nombre del archivo de resultados y realizar la redirección.

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
Gilles 'SO- deja de ser malvado'
fuente
el último realmente agradable: D
bakytn
Para ampliar la respuesta de @gilles para que sea un poco más informativo, especialmente si la lista de archivos con los que está tratando es grande, puede informar el nombre del archivo (ruta relativa) de cada archivo junto con los resultados grep'ed usando esto : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt Y si desea ver los números de línea de las líneas grep'ed que puede, por supuesto, usargrep -n "something"
JJMpls
9

Para el registro, grephas --includey --excludeargumentos que puedes usar para filtrar los archivos que busca:

grep -r --include="*.py" "something" > output.txt
Hunse
fuente
2
Al menos GNU lo grephace.
phk
2

Uso tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

La advertencia, es si tiene algún archivo con caracteres especiales (incluyendo espacios) que xargsy grepno va a funcionar bien con ( a file.txtserá interpretado como dos archivos, ay file.txt). La alternativa a eso es usar el -xo -print0, pero cualquiera de ellos contaminará su output.txt. Se -xutilizará \para escapar de ciertos caracteres especiales y esto estará en output.txt. La -print0utilizará un byte nulo como separador de campos (que también requiere xargs -0) y output.txtse verá como una larga fila contigua de texto.

La forma en que trates (o no) con esto depende de ti.

bahamat
fuente