¿Cómo ejecutar find -exec?


Respuestas:


710

Te perdiste un ;(escapaste aquí \;para evitar que el shell lo interprete) o a +y a {}:

find . -exec grep chrome {} \;

o

find . -exec grep chrome {} +

findse ejecutará grepy sustituirá {}con los nombres de archivo encontrados. La diferencia entre ;y +es que con ;un solo grepcomando para cada archivo se ejecuta mientras que con +tantos archivos como sea posible se dan como parámetros a la grepvez.


30
Si usa el \; la construcción final grep se pasa un archivo a la vez, por lo que no muestra el nombre del archivo de forma predeterminada, solo las líneas coincidentes. Para obtener una lista de archivos, agregue el uso grep -lsdentro de la construcción de búsqueda.
Caleb

99
find . -exec grep foo {} +le mostrará una salida como esta./dir/file.py:from foo import bar
sg

10
find . -exec grep foo {} \;le mostrará una salida como estafrom foo import bar
sg

99
find . -exec grep -l foo {} +le mostrará una salida como esta./dir/file.py
sg

8
find . -exec grep -l foo {} \;le mostrará una salida como esta./dir/file.py
sg

46

No necesita usar findpara esto en absoluto; grep puede manejar la apertura de archivos desde una lista global de todo en el directorio actual:

grep chrome *

... o incluso recursivamente para la carpeta y todo lo que hay debajo:

grep chrome . -R

22
grep se ahogará si la expansión supera ARG_MAX. -R visitará todo mientras usa find one puede agregar primitivas más fácilmente para excluir ciertos archivos (-name, etc.) o ni siquiera visitar subárboles (-prune).
Mel

66
Buenos puntos @Mel. Mi punto fue que, con toda probabilidad, la parte que preguntaba estaba haciendo las cosas más complejas de lo que debían ser al presentar findcuándo greppodría hacer el trabajo, pero en algunos casos sería más efectivo usar find para ajustar la lista de archivos antes de salir grep.
Caleb

44
@Mel grepno se ahoga en tal caso, execsí.
Chris Down

Funciona solo en caso de que todos los archivos estén en el mismo directorio, no cuando se distribuyen en subdirectorios.
Yaba

1
@Yaba Mi respuesta indica cómo manejar el caso de los archivos distribuidos en subdirectorios.
Caleb

18
find . | xargs grep 'chrome'

también puedes hacer:

find . | xargs grep 'chrome' -ls

El primero le muestra las líneas en los archivos, el segundo simplemente enumera los archivos.

La opción de Caleb es más ordenada, menos pulsaciones de teclas.


11
El problema con xargses que espera que su entrada sea citada de una manera peculiar que findno produce. Por find … | xargs …lo tanto , no funciona si tiene nombres de archivo que contienen espacios en blanco o \'".
Gilles

3
@Gilles Puede solucionar ese problema utilizando algo como find . | xargs -n1 -iX grep "X" 'chrome'para que los argumentos se alimenten uno a la vez y se citen. Obviamente, esta es una forma terriblemente ineficiente de manejar este ejemplo, pero para algunas situaciones es agradable.
Caleb

Para completar, también debemos mencionar la opción -i para la insensibilidad a mayúsculas y minúsculas con 'grep'. También hay -iname en find para mayúsculas y minúsculas.
Mateo

99
@Caleb: la única forma 100% confiable de hacer xargsfrente a los nombres de archivo de Linux es find ... -print0 | xargs -0usar NUL como separador. Alternativa: xargs -d '\n'usar la nueva línea como separador, 99% de confiabilidad.
Grawity

Utilizo esto a menudo, pero fallará para listas muy largas de nombres de archivo, en cuyo punto find -exec se convierte en el ganador.
Spacemoose

5

Encontrar es unidireccional y puedes probar, the_silver_searcherentonces todo lo que necesitas hacer es

ag chrome

Buscará Chrome en todos los archivos (incluidos los subdirectorios) y es más rápido que encontrar


También hay pt (buscador de platino, disponible en github.com/monochromegane/the_platinum_searcher ) que, en mi humilde opinión, hace el trabajo más rápido, puede que no importe si solo hay unos pocos archivos.
Saltando Bunny


1

Aquí hay un ejemplo de cómo suelo usar find / exec ...

find  . -name "*.py" -print -exec fgrep hello {} \;

Esto busca de forma recursiva todos los archivos .py, y para cada archivo imprime el nombre de archivo y fgrep para 'hola' en ese archivo (para cada). La salida se ve así (solo ejecuté una hoy):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"

1
para no interferir con su flujo de trabajo, pero le gustaría: find . -name "*.py" -exec fgrep -l hello {} \; - imprimirá los nombres de los archivos que coinciden, y nada más
Jeff Schaller
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.