2008-09-15 13 views
56

Estoy tratando de construir un comando find para procesar un grupo de archivos en un directorio usando dos ejecutables diferentes. Desafortunadamente, -exec en find no permite usar pipe o incluso \| porque el shell interpreta ese carácter primero.¿Cómo utilizo un conducto en el parámetro exec para un comando de búsqueda?

Aquí es específicamente lo que estoy tratando de hacer (que no funciona porque los extremos del tubo del comando find):

find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print 

Respuesta

57

probar este

find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print 

Alternativamente, usted podría tratar de integrar su declaración ejecutivo dentro de un script sh y luego hacer:

find -exec some_script {} \; 
+1

@ Martin: se coloca el apóstrofe de cierre al final de "-print", cuando debería ser al final de "123", y luego la última "\"; no es necesario. – tzot

1

Como esto da salida a una lista podría No:

find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123 

o

find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123 

Deja tus grep en los resultados de la -exec encontrar.

+0

que no funciona porque necesito el -print a trabajar. Si grep devuelve un resultado exitoso, find imprime el nombre del archivo; de lo contrario, no lo hace. – hoyhoy

+0

esto funcionó para mí, gracias por la sugerencia – Arturski

3

Con -exec sólo se puede ejecutar un solo ejecutable con algunos argumentos, no comandos de shell arbitrarios. Para evitar esto, puede usar sh -c '<shell command>'.

Tenga en cuenta que el uso de -exec es bastante ineficiente. Para cada archivo que se encuentra, el comando debe ejecutarse nuevamente. Sería más eficiente si puedes evitar esto. (Por ejemplo, moviendo el grep fuera del -exec o tuberías de los resultados de find a xargs como sugiere Palmin.)

+0

Eso está bien. Creo, sin embargo, que mi comentario sobre la (in) eficiente de -exec es también digno de mención. – mweerden

+0

Otra forma de evitar la ineficacia proceso múltiple en el caso general es utilizar xargs. Si necesita procesos separados, puede usar la opción -i. Creo que xargs es más acorde con el modelo de Unix. –

+0

uso de AOL en xargs. mweerden, tal vez deberías cambiar tu último párrafo teniendo en cuenta la existencia de xargs. También tenga en cuenta la bandera -0 que existe tanto en 'find' como' xargs'. – tzot

11

un enfoque ligeramente diferente sería utilizar xargs:

find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123 

que siempre he encontrado un poco más fácil de entender y de adaptar (los argumentos -print0 y -0 son necesarios para lidiar con nombres de archivos que contienen espacios en blanco)

podría (no probado) ser más efectivo que usar -exec b Porque canalizará la lista de archivos a xargs y xargs se asegurará de que la línea de comandos de jhead no sea demasiado larga.

+0

El problema de usar xargs aquí es que necesito el nombre del archivo que coincida. Este comando encuentra las coincidencias, pero no sé qué archivo coincide. – hoyhoy

3

El uso del comando find para este tipo de tarea quizás no sea la mejor alternativa. Yo uso el siguiente comando con frecuencia para encontrar los archivos que contienen la información solicitada:

for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done 
0

No es una especie de otra manera que puede hacerlo, pero también es bastante gueto.

Usando la opción de shell extquote puede hacer algo similar a esto para hacer encontrar cosas de exec y luego canalizarlo a sh.

[email protected] findtest # find -type f -exec echo ls $"|" cat \;|sh 
filename 


[email protected] findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh 
h 

Sólo pensé que me gustaría añadir que debido a que al menos la forma en que se visualizaba, que estaba más cerca a la pregunta original de la OP de la utilización de tubos dentro ejecutivo.

Cuestiones relacionadas