encontrar: falta argumento para -exec

encontrar: falta argumento para -exec

Estoy intentando ejecutar el siguiente comando:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

Esto devuelve un error:

find: missing argument to -exec

No veo qué hay de malo en este comando, ya que parece coincidir con la página del manual:

-comando ejecutivo {} +

Esta variante de la opción -exec ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se crea agregando cada nombre de archivo seleccionado al final; el número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando está construida de manera muy similar a como xargs construye sus líneas de comando. Sólo se permite una instancia de '{}' dentro del comando. El comando se ejecuta en el directorio de inicio.

También probé:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+

Respuesta1

Hubo varios problemas con sus intentos, incluidos comillas invertidas utilizadas en lugar de comillas (eliminadas en ediciones posteriores de la pregunta), comillas faltantes donde son necesarias, comillas adicionales donde son inútiles, paréntesis faltantes para -ocláusulas de grupo y diferentes implementaciones de findusado ( ver los comentarios y chatear para más detalles).

De todos modos, el comando se puede simplificar así:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

o, si usa una versión arcaica de búsqueda de GNU, esto siempre debería funcionar:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;

Respuesta2

"Falta el argumento de -exec" normalmente significa que al argumento de - execle falta su terminador. El terminador debe ser un argumento que contenga solo el carácter ;(que debe citarse en un comando de shell, por lo que normalmente se escribe \;o ';'), o dos argumentos sucesivos que contengan {}y +.

Stéphane Chazelas ha identificadoque estás usando una versión anterior de GNU que no es compatible -exec … {} +, solo -exec {} \;. Aunque GNU adoptó tarde -exec … {} +, le recomiendo que obtenga un conjunto de herramientas menos antiguo (comoCygwin, que incluye git y mucho más, oGNUwin32, que carece de git pero no tiene la sensación de mal empleado que intenta usar Linux pero imponemos Windows que ofrece Cygwin). Esta característica se agregó en la versión 4.2.12, hace más de 9 años (fue la última característica identificada que hizo findcompatible con GNU POSIX).

Si desea seguir con una búsqueda de GNU anterior, puede usar -print0with xargs -0para obtener una funcionalidad similar: ejecución de comandos agrupados, que admite nombres de archivos arbitrarios.

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

Cita siempre los comodines en la findlínea de comando. De lo contrario, si ejecuta este comando desde un directorio que contiene .carchivos, el comando sin comillas *.cse expandirá a la lista de .carchivos en el directorio actual.

Agregar /dev/nulla la greplínea de comando es un truco para garantizar que grep siempre imprima el nombre del archivo, incluso si findencuentra una sola coincidencia. Con GNU find, otro método es pasar la opción -H.

Respuesta3

Si un comando como

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

devuelve error

find: missing argument to -exec

la causa probable es que GNU es demasiado antiguo findy no admite sintaxis -exec mycommand {} +. En ese caso, se ejecuta un reemplazo de bajo rendimiento -exec mycommand {} \;que ejecutará una mycommandvez por cada objetivo encontrado en lugar de recopilar múltiples objetivos y ejecutar mycommandsolo una vez.

Sin embargo, GNU findno soporta, por ejemplo

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

porque GNU findsolo admite combinaciones literales {} +en lugar de más genéricas {} additional parameters +. Tenga en cuenta que no puede haber nada entre las llaves y el +carácter. Si intenta esto, obtendrá el mismo error:

find: missing argument to -exec

La solución es utilizar una sintaxis {} additional parameters \;que funcione pero ejecutará el comando una vez por cada objetivo encontrado. Si necesita más rendimiento con GNU, finddebe escribir un script contenedor que pueda agregar parámetros adicionales a los argumentos proporcionados. Algo como

#!/bin/bash
exec mycommand "$@" additional parameters

debería ser lo suficientemente bueno. O, si no desea crear un archivo temporal, puede utilizar una sola línea para cambiar el orden de los parámetros como este:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

que ejecutará mycommand {list of ttf files} extra arguments. Tenga en cuenta que es posible que necesite utilizar caracteres especiales de escape doble para el bash después de la -cbandera.

Respuesta4

Tuve algunos dolores de cabeza con la sintaxis ejecutiva en el pasado. La mayoría de los días prefiero la sintaxis bash más agradable:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

Tiene algunas limitaciones cuando desea tratar los archivos como un grupo, ya que cada uno se evalúa en serie, pero puede canalizar la salida a otro lugar sin problemas.

información relacionada