¿Cómo ejecutar find -exec?

477

Me gustaría encontrar los archivos en el directorio actual que contienen el texto "Chrome".

$ find . -exec grep chrome
find: missing argument to `-exec'

¿Qué estoy haciendo mal?

ripper234
fuente
Tengofind: Only one instance of {} is supported with -exec ... +
Costa
2
Relacionado: Cómo usar -execconfind
Kusalananda

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.

bmk
fuente
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
Caleb
fuente
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.

Mateo
fuente
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

Pregunta y aprende
fuente
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

Para ver la lista de archivos en lugar de líneas:

grep -l "chrome" *

o:

grep -r -l "chrome" .
mateusz.szymborski
fuente
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"
jon
fuente
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